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: berkley $'
10
 *     '$Date: 2003-07-02 12:09:37 -0700 (Wed, 02 Jul 2003) $'
11
 * '$Revision: 1717 $'
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.util.Vector;
47
import java.net.URL;
48
import java.net.MalformedURLException;
49
import java.sql.PreparedStatement;
50
import java.sql.ResultSet;
51
import java.sql.Connection;
52
import java.sql.SQLException;
53
import java.lang.reflect.*;
54
import java.net.*;
55
import java.util.zip.*;
56

    
57
import javax.servlet.ServletConfig;
58
import javax.servlet.ServletContext;
59
import javax.servlet.ServletException;
60
import javax.servlet.ServletInputStream;
61
import javax.servlet.http.HttpServlet;
62
import javax.servlet.http.HttpServletRequest;
63
import javax.servlet.http.HttpServletResponse;
64
import javax.servlet.http.HttpSession;
65
import javax.servlet.http.HttpUtils;
66
import javax.servlet.ServletOutputStream;
67

    
68
import org.ecoinformatics.eml.EMLParser;
69

    
70
import org.xml.sax.SAXException;
71

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

    
109
  private ServletConfig config = null;
110
  private ServletContext context = null;
111
  private String resultStyleURL = null;
112
  private String xmlcatalogfile = null;
113
  private String saxparser = null;
114
  private String datafilepath = null;
115
  private File dataDirectory = null;
116
  private String servletpath = null;
117
  private String htmlpath = null;
118
  private PropertyResourceBundle options = null;
119
  private MetaCatUtil util = null;
120
  private DBConnectionPool connPool = null;
121
  private static final String PROLOG = "<?xml version=\"1.0\"?>";
122
  private static final String SUCCESS = "<success>";
123
  private static final String SUCCESSCLOSE = "</success>";
124
  private static final String ERROR = "<error>";
125
  private static final String ERRORCLOSE = "</error>";
126
  public static final String SCHEMALOCATIONKEYWORD = ":schemaLocation";
127
  public static final String NONAMESPACELOCATION = ":noNamespaceSchemaLocation";
128
  public static final String EML2KEYWORD =":eml";
129

    
130
  /**
131
   * Initialize the servlet by creating appropriate database connections
132
   */
133
  public void init( ServletConfig config ) throws ServletException {
134
    try {
135
      super.init( config );
136
      this.config = config;
137
      this.context = config.getServletContext();
138
      System.out.println("MetaCatServlet Initialize");
139

    
140
      util = new MetaCatUtil();
141

    
142
      //initial DBConnection pool
143
      connPool = DBConnectionPool.getInstance();
144

    
145
      // Get the configuration file information
146
      resultStyleURL = util.getOption("resultStyleURL");
147
      xmlcatalogfile = util.getOption("xmlcatalogfile");
148
      saxparser = util.getOption("saxparser");
149
      datafilepath = util.getOption("datafilepath");
150
      dataDirectory = new File(datafilepath);
151
      servletpath = util.getOption("servletpath");
152
      htmlpath = util.getOption("htmlpath");
153

    
154

    
155
    } catch ( ServletException ex ) {
156
      throw ex;
157
    } catch (SQLException e) {
158
      MetaCatUtil.debugMessage("Error in MetacatServlet.init: "
159
                                          +e.getMessage(), 20);
160
    }
161
  }
162

    
163
  /**
164
   * Close all db connections from the pool
165
   */
166
  public void destroy() {
167
      // Close all db connection
168
      System.out.println("Destroying MetacatServlet");
169
      connPool.release();
170
  }
171

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

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

    
180
  /** Handle "POST" method requests from HTTP clients */
181
  public void doPost( HttpServletRequest request, HttpServletResponse response)
182
    throws ServletException, IOException {
183

    
184
    // Process the data and send back the response
185
    handleGetOrPost(request, response);
186
  }
187

    
188
  /**
189
   * Control servlet response depending on the action parameter specified
190
   */
191
  private void handleGetOrPost(HttpServletRequest request,
192
                               HttpServletResponse response)
193
                               throws ServletException, IOException
194
  {
195

    
196
    if ( util == null ) {
197
        util = new MetaCatUtil();
198
    }
199
    /*MetaCatUtil.debugMessage("Connection pool size: "
200
                                     +connPool.getSizeOfDBConnectionPool(),10);
201
    MetaCatUtil.debugMessage("Free DBConnection number: "
202
                                  +connPool.getFreeDBConnectionNumber(), 10);*/
203
    //If all DBConnection in the pool are free and DBConnection pool
204
    //size is greater than initial value, shrink the connection pool
205
    //size to initial value
206
    DBConnectionPool.shrinkDBConnectionPoolSize();
207

    
208
    //Debug message to print out the method which have a busy DBConnection
209
    connPool.printMethodNameHavingBusyDBConnection();
210

    
211
    String ctype = request.getContentType();
212
    if (ctype != null && ctype.startsWith("multipart/form-data")) {
213
      handleMultipartForm(request, response);
214
    } else {
215

    
216

    
217
      String name = null;
218
      String[] value = null;
219
      String[] docid = new String[3];
220
      Hashtable params = new Hashtable();
221
      Enumeration paramlist = request.getParameterNames();
222

    
223

    
224
      while (paramlist.hasMoreElements()) {
225

    
226
        name = (String)paramlist.nextElement();
227
        value = request.getParameterValues(name);
228

    
229
        // Decode the docid and mouse click information
230
        if (name.endsWith(".y")) {
231
          docid[0] = name.substring(0,name.length()-2);
232
          params.put("docid", docid);
233
          name = "ypos";
234
        }
235
        if (name.endsWith(".x")) {
236
          name = "xpos";
237
        }
238

    
239
        params.put(name,value);
240
      }
241

    
242

    
243
      //handle param is emptpy
244
      if (params.isEmpty() || params == null)
245
      {
246
        return;
247
      }
248

    
249
      //if the user clicked on the input images, decode which image
250
      //was clicked then set the action.
251
      String action = ((String[])params.get("action"))[0];
252
      util.debugMessage("Line 230: Action is: " + action, 1);
253

    
254
      // This block handles session management for the servlet
255
      // by looking up the current session information for all actions
256
      // other than "login" and "logout"
257
      String username = null;
258
      String password = null;
259
      String[] groupnames = null;
260
      String sess_id = null;
261

    
262
      // handle login action
263
      if (action.equals("login")) {
264
        PrintWriter out = response.getWriter();
265
        handleLoginAction(out, params, request, response);
266
        out.close();
267

    
268
      // handle logout action
269
      } else if (action.equals("logout")) {
270
        PrintWriter out = response.getWriter();
271
        handleLogoutAction(out, params, request, response);
272
        out.close();
273

    
274
      // handle shrink DBConnection request
275
      } else if (action.equals("shrink")) {
276
        PrintWriter out = response.getWriter();
277
        boolean success = false;
278
        //If all DBConnection in the pool are free and DBConnection pool
279
        //size is greater than initial value, shrink the connection pool
280
        //size to initial value
281
        success = DBConnectionPool.shrinkConnectionPoolSize();
282
        if (success)
283
        {
284
          //if successfully shrink the pool size to initial value
285
          out.println("DBConnection Pool shrink successfully");
286
        }//if
287
        else
288
        {
289
          out.println("DBConnection pool couldn't shrink successfully");
290
        }
291
       //close out put
292
        out.close();
293

    
294
      // aware of session expiration on every request
295
      } else {
296

    
297
        HttpSession sess = request.getSession(true);
298
        if (sess.isNew()) {
299
          // session expired or has not been stored b/w user requests
300
          username = "public";
301
          sess.setAttribute("username", username);
302
        } else {
303
          username = (String)sess.getAttribute("username");
304
          password = (String)sess.getAttribute("password");
305
          groupnames = (String[])sess.getAttribute("groupnames");
306
          try {
307
            if(params.containsKey("sessionid"))
308
            {
309
              sess_id = (String)params.get("sessionid");
310
              sess.setAttribute("JSESSIONID", sess_id);
311
            }
312
            else
313
            {
314
              sess_id = (String)sess.getId();
315
            }
316
          } catch(IllegalStateException ise) {
317
            System.out.println("error in handleGetOrPost: this shouldn't " +
318
                               "happen: the session should be valid: " +
319
                               ise.getMessage());
320
          }
321
        }
322
      }
323

    
324
       // Now that we know the session is valid, we can delegate the request
325
      // to a particular action handler
326
      if(action.equals("query")) {
327
        PrintWriter out = response.getWriter();
328
        handleQuery(out,params,response,username,groupnames,sess_id);
329
        out.close();
330
      } else if(action.equals("squery")) {
331
        PrintWriter out = response.getWriter();
332
        if(params.containsKey("query")) {
333
         handleSQuery(out, params,response,username,groupnames,sess_id);
334
         out.close();
335
        } else {
336
          out.println("Illegal action squery without \"query\" parameter");
337
          out.close();
338
        }
339
      } else if (action.equals("export")) {
340

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

    
450
      //util.closeConnections();
451
      // Close the stream to the client
452
      //out.close();
453
    }
454
  }
455

    
456
  // LOGIN & LOGOUT SECTION
457
  /**
458
   * Handle the login request. Create a new session object.
459
   * Do user authentication through the session.
460
   */
461
  private void handleLoginAction(PrintWriter out, Hashtable params,
462
               HttpServletRequest request, HttpServletResponse response) {
463

    
464
    AuthSession sess = null;
465
    String un = ((String[])params.get("username"))[0];
466
    String pw = ((String[])params.get("password"))[0];
467
    String action = ((String[])params.get("action"))[0];
468
    String qformat = ((String[])params.get("qformat"))[0];
469

    
470
    try {
471
      sess = new AuthSession();
472
    } catch (Exception e) {
473
      System.out.println("error in MetacatServlet.handleLoginAction: " +
474
                          e.getMessage());
475
      out.println(e.getMessage());
476
      return;
477
    }
478
    boolean isValid = sess.authenticate(request, un, pw);
479
    // format and transform the output
480
    if (qformat.equals("xml")) {
481
      response.setContentType("text/xml");
482
      out.println(sess.getMessage());
483
    } else {
484

    
485
      try {
486

    
487
        DBTransform trans = new DBTransform();
488
        response.setContentType("text/html");
489
        trans.transformXMLDocument(sess.getMessage(), "-//NCEAS//login//EN",
490
                                   "-//W3C//HTML//EN", qformat, out, null);
491

    
492
      } catch(Exception e) {
493

    
494
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLoginAction: "
495
                                +e.getMessage(), 30);
496
      }
497

    
498
    // any output is returned
499
    }
500
  }
501

    
502
  /**
503
   * Handle the logout request. Close the connection.
504
   */
505
  private void handleLogoutAction(PrintWriter out, Hashtable params,
506
               HttpServletRequest request, HttpServletResponse response) {
507

    
508
    String qformat = ((String[])params.get("qformat"))[0];
509

    
510
    // close the connection
511
    HttpSession sess = request.getSession(false);
512
    if (sess != null) { sess.invalidate();  }
513

    
514
    // produce output
515
    StringBuffer output = new StringBuffer();
516
    output.append("<?xml version=\"1.0\"?>");
517
    output.append("<logout>");
518
    output.append("User logged out");
519
    output.append("</logout>");
520

    
521
    //format and transform the output
522
    if (qformat.equals("xml")) {
523
      response.setContentType("text/xml");
524
      out.println(output.toString());
525
    } else {
526

    
527
      try {
528

    
529
        DBTransform trans = new DBTransform();
530
        response.setContentType("text/html");
531
        trans.transformXMLDocument(output.toString(), "-//NCEAS//login//EN",
532
                                   "-//W3C//HTML//EN", qformat, out, null);
533

    
534
      } catch(Exception e) {
535

    
536
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLogoutAction"
537
                                  +e.getMessage(), 30);
538
      }
539
    }
540
  }
541
  // END OF LOGIN & LOGOUT SECTION
542

    
543
  // SQUERY & QUERY SECTION
544
  /**
545
   * Retreive the squery xml, execute it and display it
546
   *
547
   * @param out the output stream to the client
548
   * @param params the Hashtable of parameters that should be included
549
   * in the squery.
550
   * @param response the response object linked to the client
551
   * @param conn the database connection
552
   */
553
  protected void handleSQuery(PrintWriter out, Hashtable params,
554
                 HttpServletResponse response, String user, String[] groups,
555
                 String sessionid)
556
  {
557
    String xmlquery = ((String[])params.get("query"))[0];
558
    String qformat = ((String[])params.get("qformat"))[0];
559
    String resultdoc = null;
560
    MetaCatUtil.debugMessage("xmlquery: "+xmlquery, 30);
561
    double startTime = System.currentTimeMillis()/1000;
562
    Hashtable doclist = runQuery(xmlquery, user, groups);
563
    double docListTime = System.currentTimeMillis()/1000;
564
    MetaCatUtil.debugMessage("Time for getting doc list: "
565
                                            +(docListTime-startTime), 30);
566

    
567
    resultdoc = createResultDocument(doclist, transformQuery(xmlquery));
568
    double toStringTime = System.currentTimeMillis()/1000;
569
    MetaCatUtil.debugMessage("Time to create xml string: "
570
                              +(toStringTime-docListTime), 30);
571
    //format and transform the results
572
    double outPutTime = 0;
573
    if(qformat.equals("xml")) {
574
      response.setContentType("text/xml");
575
      out.println(resultdoc);
576
      outPutTime = System.currentTimeMillis()/1000;
577
      MetaCatUtil.debugMessage("Output time: "+(outPutTime-toStringTime), 30);
578
    } else {
579
      transformResultset(resultdoc, response, out, qformat, sessionid);
580
      outPutTime = System.currentTimeMillis()/1000;
581
      MetaCatUtil.debugMessage("Output time: "+(outPutTime-toStringTime), 30);
582
    }
583
  }
584

    
585
   /**
586
    * Create the xml query, execute it and display the results.
587
    *
588
    * @param out the output stream to the client
589
    * @param params the Hashtable of parameters that should be included
590
    * in the squery.
591
    * @param response the response object linked to the client
592
    */
593
  protected void handleQuery(PrintWriter out, Hashtable params,
594
                 HttpServletResponse response, String user, String[] groups,
595
                 String sessionid)
596
  {
597
    //create the query and run it
598
    String xmlquery = DBQuery.createSQuery(params);
599
    Hashtable doclist = runQuery(xmlquery, user, groups);
600
    String qformat = ((String[])params.get("qformat"))[0];
601
    String resultdoc = null;
602

    
603
    resultdoc = createResultDocument(doclist, transformQuery(params));
604

    
605
    //format and transform the results
606
    if(qformat.equals("xml")) {
607
      response.setContentType("text/xml");
608
      out.println(resultdoc);
609
    } else {
610
      transformResultset(resultdoc, response, out, qformat, sessionid);
611
    }
612
  }
613

    
614
  /**
615
   * Removes the <?xml version="x"?> tag from the beginning of xmlquery
616
   * so it can properly be placed in the <query> tag of the resultset.
617
   * This method is overwritable so that other applications can customize
618
   * the structure of what is in the <query> tag.
619
   *
620
   * @param xmlquery is the query to remove the <?xml version="x"?> tag from.
621
   */
622
  protected String transformQuery(Hashtable params)
623
  {
624
    //DBQuery.createSQuery is a re-calling of a previously called
625
    //function but it is necessary
626
    //so that overriding methods have access to the params hashtable
627
    String xmlquery = DBQuery.createSQuery(params);
628
    //the <?xml version="1.0"?> tag is the first 22 characters of the
629
    xmlquery = xmlquery.trim();
630
    int index = xmlquery.indexOf("?>");
631
    return xmlquery.substring(index + 2, xmlquery.length());
632
  }
633

    
634
  /**
635
   * removes the <?xml version="1.0"?> tag from the beginning.  This takes a
636
   * string as a param instead of a hashtable.
637
   *
638
   * @param xmlquery a string representing a query.
639
   */
640
  protected String transformQuery(String xmlquery)
641
  {
642
    xmlquery = xmlquery.trim();
643
    int index = xmlquery.indexOf("?>");
644
    return xmlquery.substring(index + 2, xmlquery.length());
645
  }
646

    
647
  /**
648
   * Run the query and return a hashtable of results.
649
   *
650
   * @param xmlquery the query to run
651
   */
652
  private Hashtable runQuery(String xmlquery, String user, String[] groups)
653
  {
654
    Hashtable doclist=null;
655

    
656
    try
657
    {
658

    
659
      DBQuery queryobj = new DBQuery(saxparser);
660
      doclist = queryobj.findDocuments(new StringReader(xmlquery),user,groups);
661

    
662
      return doclist;
663
    }
664
    catch (Exception e)
665
    {
666

    
667
      MetaCatUtil.debugMessage("Error in MetacatServlet.runQuery: "
668
                                                      + e.getMessage(), 30);
669
      doclist = null;
670
      return doclist;
671
    }
672
  }
673

    
674
  /**
675
   * Transorms an xml resultset document to html and sends it to the browser
676
   *
677
   * @param resultdoc the string representation of the document that needs
678
   * to be transformed.
679
   * @param response the HttpServletResponse object bound to the client.
680
   * @param out the output stream to the client
681
   * @param qformat the name of the style-set to use for transformations
682
   */
683
  protected void transformResultset(String resultdoc,
684
                                    HttpServletResponse response,
685
                                    PrintWriter out, String qformat,
686
                                    String sessionid)
687
  {
688

    
689
    try {
690

    
691
      DBTransform trans = new DBTransform();
692
      response.setContentType("text/html");
693
      trans.transformXMLDocument(resultdoc, "-//NCEAS//resultset//EN",
694
                                 "-//W3C//HTML//EN", qformat, out, null,
695
                                 sessionid);
696

    
697
    }
698
    catch(Exception e)
699
    {
700

    
701
      MetaCatUtil.debugMessage("Error in MetaCatServlet.transformResultset:"
702
                                +e.getMessage(), 30);
703
    }
704
  }
705

    
706
  /**
707
   * Transforms a hashtable of documents to an xml or html result.
708
   *
709
   * @param doclist- the hashtable to transform
710
   * @param xmlquery- the query that returned the doclist result
711
   */
712
  protected String createResultDocument(Hashtable doclist, String xmlquery)
713
  {
714
    // Create a buffer to hold the xml result
715
    StringBuffer resultset = new StringBuffer();
716

    
717
    // Print the resulting root nodes
718
    String docid = null;
719
    String document = null;
720
    resultset.append("<?xml version=\"1.0\"?>\n");
721
    resultset.append("<resultset>\n");
722

    
723
    resultset.append("  <query>" + xmlquery + "</query>");
724

    
725
    if(doclist != null)
726
    {
727
      Enumeration doclistkeys = doclist.keys();
728
      while (doclistkeys.hasMoreElements())
729
      {
730
        docid = (String)doclistkeys.nextElement();
731
        document = (String)doclist.get(docid);
732
        resultset.append("  <document>" + document + "</document>");
733
      }
734
    }
735

    
736
    resultset.append("</resultset>");
737
    return resultset.toString();
738
  }
739
  // END OF SQUERY & QUERY SECTION
740

    
741
 //Exoport section
742
 /**
743
   * Handle the "export" request of data package from Metacat in zip format
744
   * @param params the Hashtable of HTTP request parameters
745
   * @param response the HTTP response object linked to the client
746
   * @param user the username sent the request
747
   * @param groups the user's groupnames
748
   */
749
  private void handleExportAction(Hashtable params,
750
    HttpServletResponse response, String user, String[] groups, String passWord)
751
  {
752
    // Output stream
753
    ServletOutputStream out = null;
754
    // Zip output stream
755
    ZipOutputStream zOut = null;
756
    DocumentImpl docImpls=null;
757
    DBQuery queryObj=null;
758

    
759
    String[] docs = new String[10];
760
    String docId = "";
761

    
762
    try
763
    {
764
      // read the params
765
      if (params.containsKey("docid"))
766
      {
767
        docs = (String[])params.get("docid");
768
      }//if
769
      // Create a DBuery to handle export
770
      queryObj = new DBQuery(saxparser);
771
      // Get the docid
772
      docId=docs[0];
773
      // Make sure the client specify docid
774
      if (docId == null || docId.equals(""))
775
      {
776
        response.setContentType("text/xml"); //MIME type
777
        // Get a printwriter
778
        PrintWriter pw = response.getWriter();
779
        // Send back message
780
        pw.println("<?xml version=\"1.0\"?>");
781
        pw.println("<error>");
782
        pw.println("You didn't specify requested docid");
783
        pw.println("</error>");
784
        // Close printwriter
785
        pw.close();
786
        return;
787
      }//if
788
      // Get output stream
789
      out = response.getOutputStream();
790
      response.setContentType("application/zip"); //MIME type
791
      zOut = new ZipOutputStream(out);
792
      zOut =queryObj.getZippedPackage(docId, out, user, groups, passWord);
793
      zOut.finish(); //terminate the zip file
794
      zOut.close();  //close the zip stream
795

    
796
    }//try
797
    catch (Exception e)
798
    {
799
      try
800
      {
801
        response.setContentType("text/xml"); //MIME type
802
        // Send error message back
803
        if (out != null)
804
        {
805
            PrintWriter pw = new PrintWriter(out);
806
            pw.println("<?xml version=\"1.0\"?>");
807
            pw.println("<error>");
808
            pw.println(e.getMessage());
809
            pw.println("</error>");
810
            // Close printwriter
811
            pw.close();
812
            // Close output stream
813
            out.close();
814
        }//if
815
        // Close zip output stream
816
        if ( zOut != null )
817
        {
818
          zOut.close();
819
        }//if
820
      }//try
821
      catch (IOException ioe)
822
      {
823
        MetaCatUtil.debugMessage("Problem with the servlet output " +
824
                           "in MetacatServlet.handleExportAction: " +
825
                           ioe.getMessage(), 30);
826
      }//catch
827

    
828
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleExportAction: " +
829
                         e.getMessage(), 30);
830
      e.printStackTrace(System.out);
831

    
832
    }//catch
833

    
834
  }//handleExportAction
835

    
836

    
837
   //read inline data section
838
 /**
839
   * In eml2 document, the xml can have inline data and data was stripped off
840
   * and store in file system. This action can be used to read inline data only
841
   * @param params the Hashtable of HTTP request parameters
842
   * @param response the HTTP response object linked to the client
843
   * @param user the username sent the request
844
   * @param groups the user's groupnames
845
   */
846
  private void handleReadInlineDataAction(Hashtable params,
847
                                          HttpServletResponse response,
848
                                          String user, String passWord,
849
                                          String[] groups)
850
  {
851
    String[] docs = new String[10];
852
    String inlineDataId = null;
853
    String docId = "";
854
    ServletOutputStream out = null;
855

    
856
    try
857
    {
858
      // read the params
859
      if (params.containsKey("inlinedataid"))
860
      {
861
        docs = (String[])params.get("inlinedataid");
862
      }//if
863
      // Get the docid
864
      inlineDataId=docs[0];
865
      // Make sure the client specify docid
866
      if (inlineDataId == null || inlineDataId.equals(""))
867
      {
868
        throw new Exception("You didn't specify requested inlinedataid");
869
      }//if
870

    
871
      // check for permission
872
      docId = MetaCatUtil.getDocIdWithoutRevFromInlineDataID(inlineDataId);
873
      PermissionController controller = new PermissionController(docId);
874
      // check top level read permission
875
      if (!controller.hasPermission(user, groups,
876
                                    AccessControlInterface.READSTRING))
877
      {
878
          throw new Exception("User "+ user + " doesn't have permission "+
879
                              " to read document " + docId);
880
      }//if
881
      // if the document has subtree control, we need to check subtree control
882
      else if(controller.hasSubTreeAccessControl())
883
      {
884
        // get node id for inlinedata
885
        long nodeId=getInlineDataNodeId(inlineDataId, docId);
886
        if (!controller.hasPermissionForSubTreeNode(user, groups,
887
                                     AccessControlInterface.READSTRING, nodeId))
888
        {
889
           throw new Exception("User "+ user + " doesn't have permission "+
890
                              " to read inlinedata " + inlineDataId);
891
        }//if
892

    
893
      }//else
894

    
895
      // Get output stream
896
      out = response.getOutputStream();
897
      // read the inline data from the file
898
      String inlinePath = MetaCatUtil.getOption("inlinedatafilepath");
899
      File lineData = new File(inlinePath, inlineDataId);
900
      FileInputStream input = new FileInputStream(lineData);
901
      byte [] buffer = new byte[4*1024];
902
      int bytes = input.read(buffer);
903
      while (bytes != -1)
904
      {
905
        out.write(buffer, 0, bytes);
906
        bytes = input.read(buffer);
907
      }
908
      out.close();
909

    
910
    }//try
911
    catch (Exception e)
912
    {
913
      try
914
      {
915
        PrintWriter pw = null;
916
        // Send error message back
917
        if (out != null)
918
        {
919
            pw = new PrintWriter(out);
920
        }//if
921
        else
922
        {
923
          pw = response.getWriter();
924
        }
925
         pw.println("<?xml version=\"1.0\"?>");
926
         pw.println("<error>");
927
         pw.println(e.getMessage());
928
         pw.println("</error>");
929
         // Close printwriter
930
         pw.close();
931
         // Close output stream if out is not null
932
         if (out != null)
933
         {
934
           out.close();
935
         }
936
     }//try
937
     catch (IOException ioe)
938
     {
939
        MetaCatUtil.debugMessage("Problem with the servlet output " +
940
                           "in MetacatServlet.handleExportAction: " +
941
                           ioe.getMessage(), 30);
942
     }//catch
943

    
944
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleReadInlineDataAction: "
945
                                + e.getMessage(), 30);
946

    
947
    }//catch
948

    
949
  }//handleReadInlineDataAction
950

    
951
  /*
952
   * Get the nodeid from xml_nodes for the inlinedataid
953
   */
954
  private long getInlineDataNodeId(String inLineDataId, String docId)
955
                                   throws SQLException
956
  {
957
    long nodeId = 0;
958
    String INLINE = "inline";
959
    boolean hasRow;
960
    PreparedStatement pStmt = null;
961
    DBConnection conn = null;
962
    int serialNumber = -1;
963
    String sql ="SELECT nodeid FROM xml_nodes WHERE docid=? AND nodedata=? " +
964
                "AND nodetype='TEXT' AND parentnodeid IN " +
965
                "(SELECT nodeid FROM xml_nodes WHERE docid=? AND " +
966
                "nodetype='ELEMENT' AND nodename='" + INLINE + "')";
967

    
968
    try
969
    {
970
      //check out DBConnection
971
      conn=DBConnectionPool.getDBConnection("AccessControlList.isAllowFirst");
972
      serialNumber=conn.getCheckOutSerialNumber();
973

    
974
      pStmt = conn.prepareStatement(sql);
975
      //bind value
976
      pStmt.setString(1, docId);//docid
977
      pStmt.setString(2, inLineDataId);//inlinedataid
978
      pStmt.setString(3, docId);
979
      // excute query
980
      pStmt.execute();
981
      ResultSet rs = pStmt.getResultSet();
982
      hasRow=rs.next();
983
      // get result
984
      if (hasRow)
985
      {
986
        nodeId = rs.getLong(1);
987
      }//if
988

    
989
    }//try
990
    catch (SQLException e)
991
    {
992
      throw e;
993
    }
994
    finally
995
    {
996
      try
997
      {
998
        pStmt.close();
999
      }
1000
      finally
1001
      {
1002
        DBConnectionPool.returnDBConnection(conn, serialNumber);
1003
      }
1004
    }
1005
    MetaCatUtil.debugMessage("The nodeid for inlinedataid " + inLineDataId +
1006
                             " is: "+nodeId, 35);
1007
    return nodeId;
1008
  }
1009

    
1010

    
1011

    
1012
  // READ SECTION
1013
  /**
1014
   * Handle the "read" request of metadata/data files from Metacat
1015
   * or any files from Internet;
1016
   * transformed metadata XML document into HTML presentation if requested;
1017
   * zip files when more than one were requested.
1018
   *
1019
   * @param params the Hashtable of HTTP request parameters
1020
   * @param response the HTTP response object linked to the client
1021
   * @param user the username sent the request
1022
   * @param groups the user's groupnames
1023
   */
1024
  private void handleReadAction(Hashtable params, HttpServletResponse response,
1025
                                String user, String passWord, String[] groups)
1026
  {
1027
    ServletOutputStream out = null;
1028
    ZipOutputStream zout = null;
1029
    PrintWriter pw = null;
1030
    boolean zip = false;
1031
    boolean withInlineData = true;
1032

    
1033
    try {
1034
      String[] docs = new String[0];
1035
      String docid = "";
1036
      String qformat = "";
1037
      String abstrpath = null;
1038

    
1039
      // read the params
1040
      if (params.containsKey("docid")) {
1041
        docs = (String[])params.get("docid");
1042
      }
1043
      if (params.containsKey("qformat")) {
1044
        qformat = ((String[])params.get("qformat"))[0];
1045
      }
1046
      // the param for only metadata (eml)
1047
      if (params.containsKey("inlinedata"))
1048
      {
1049

    
1050
        String inlineData = ((String[])params.get("inlinedata"))[0];
1051
        if (inlineData.equalsIgnoreCase("false"))
1052
        {
1053
          withInlineData = false;
1054
        }
1055
      }
1056
      if (params.containsKey("abstractpath")) {
1057
        abstrpath = ((String[])params.get("abstractpath"))[0];
1058
        if ( !abstrpath.equals("") && (abstrpath != null) ) {
1059
          viewAbstract(response, abstrpath, docs[0]);
1060
          return;
1061
        }
1062
      }
1063
      if ( (docs.length > 1) || qformat.equals("zip") ) {
1064
        zip = true;
1065
        out = response.getOutputStream();
1066
        response.setContentType("application/zip"); //MIME type
1067
        zout = new ZipOutputStream(out);
1068
      }
1069
      // go through the list of docs to read
1070
      for (int i=0; i < docs.length; i++ ) {
1071
        try {
1072

    
1073
          URL murl = new URL(docs[i]);
1074
          Hashtable murlQueryStr = util.parseQuery(murl.getQuery());
1075
          // case docid="http://.../?docid=aaa"
1076
          // or docid="metacat://.../?docid=bbb"
1077
          if (murlQueryStr.containsKey("docid")) {
1078
            // get only docid, eliminate the rest
1079
            docid = (String)murlQueryStr.get("docid");
1080
            if ( zip ) {
1081
              addDocToZip(docid, zout, user, groups);
1082
            } else {
1083
              readFromMetacat(response, docid, qformat, abstrpath,
1084
                              user, groups, zip, zout, withInlineData, params);
1085
            }
1086

    
1087
          // case docid="http://.../filename"
1088
          } else {
1089
            docid = docs[i];
1090
            if ( zip ) {
1091
              addDocToZip(docid, zout, user, groups);
1092
            } else {
1093
              readFromURLConnection(response, docid);
1094
            }
1095
          }
1096

    
1097
        // case docid="ccc"
1098
        } catch (MalformedURLException mue) {
1099
          docid = docs[i];
1100
          if ( zip ) {
1101
            addDocToZip(docid, zout, user, groups);
1102
          } else {
1103
            readFromMetacat(response, docid, qformat, abstrpath,
1104
                            user, groups, zip, zout, withInlineData, params);
1105
          }
1106
        }
1107

    
1108
      } /* end for */
1109

    
1110
      if ( zip ) {
1111
        zout.finish(); //terminate the zip file
1112
        zout.close();  //close the zip stream
1113
      }
1114

    
1115

    
1116
    }
1117
    // To handle doc not found exception
1118
    catch (McdbDocNotFoundException notFoundE)
1119
    {
1120
      // the docid which didn't be found
1121
      String notFoundDocId = notFoundE.getUnfoundDocId();
1122
      String notFoundRevision = notFoundE.getUnfoundRevision();
1123
      MetaCatUtil.debugMessage("Missed id: "+ notFoundDocId, 30);
1124
      MetaCatUtil.debugMessage("Missed rev: "+ notFoundRevision, 30);
1125
      try
1126
      {
1127
        // read docid from remote server
1128
        readFromRemoteMetaCat(response, notFoundDocId, notFoundRevision,
1129
                                              user, passWord, out, zip, zout);
1130
        // Close zout outputstream
1131
        if ( zout != null)
1132
        {
1133
          zout.close();
1134
        }
1135
        // close output stream
1136
        if (out != null)
1137
        {
1138
          out.close();
1139
        }
1140

    
1141
      }//try
1142
      catch ( Exception exc)
1143
      {
1144
        MetaCatUtil.debugMessage("Erorr in MetacatServlet.hanldReadAction: "+
1145
                                      exc.getMessage(), 30);
1146
        try
1147
        {
1148
          if (out != null)
1149
          {
1150
            response.setContentType("text/xml");
1151
            // Send back error message by printWriter
1152
            pw = new PrintWriter(out);
1153
            pw.println("<?xml version=\"1.0\"?>");
1154
            pw.println("<error>");
1155
            pw.println(notFoundE.getMessage());
1156
            pw.println("</error>");
1157
            pw.close();
1158
            out.close();
1159

    
1160
          }
1161
          else
1162
          {
1163
           response.setContentType("text/xml"); //MIME type
1164
           // Send back error message if out = null
1165
           if (pw == null)
1166
           {
1167
             // If pw is null, open the respnose
1168
            pw = response.getWriter();
1169
           }
1170
           pw.println("<?xml version=\"1.0\"?>");
1171
           pw.println("<error>");
1172
           pw.println(notFoundE.getMessage());
1173
           pw.println("</error>");
1174
           pw.close();
1175
        }
1176
        // close zout
1177
        if ( zout != null )
1178
        {
1179
          zout.close();
1180
        }
1181
        }//try
1182
        catch (IOException ie)
1183
        {
1184
          MetaCatUtil.debugMessage("Problem with the servlet output " +
1185
                           "in MetacatServlet.handleReadAction: " +
1186
                           ie.getMessage(), 30);
1187
        }//cathch
1188
      }//catch
1189
    }// catch McdbDocNotFoundException
1190
    catch (Exception e)
1191
    {
1192
      try {
1193

    
1194
        if (out != null) {
1195
            response.setContentType("text/xml"); //MIME type
1196
            pw = new PrintWriter(out);
1197
            pw.println("<?xml version=\"1.0\"?>");
1198
            pw.println("<error>");
1199
            pw.println(e.getMessage());
1200
            pw.println("</error>");
1201
            pw.close();
1202
            out.close();
1203
        }
1204
        else
1205
        {
1206
           response.setContentType("text/xml"); //MIME type
1207
           // Send back error message if out = null
1208
           if ( pw == null)
1209
           {
1210
            pw = response.getWriter();
1211
           }
1212
           pw.println("<?xml version=\"1.0\"?>");
1213
           pw.println("<error>");
1214
           pw.println(e.getMessage());
1215
           pw.println("</error>");
1216
           pw.close();
1217

    
1218
        }
1219
        // Close zip output stream
1220
        if ( zout != null ) { zout.close(); }
1221

    
1222
      } catch (IOException ioe) {
1223
        MetaCatUtil.debugMessage("Problem with the servlet output " +
1224
                           "in MetacatServlet.handleReadAction: " +
1225
                           ioe.getMessage(), 30);
1226
        ioe.printStackTrace(System.out);
1227

    
1228
      }
1229

    
1230
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleReadAction: " +
1231
                               e.getMessage(), 30);
1232
      //e.printStackTrace(System.out);
1233
    }
1234

    
1235
  }
1236

    
1237
  // read metadata or data from Metacat
1238
  private void readFromMetacat(HttpServletResponse response, String docid,
1239
                               String qformat, String abstrpath, String user,
1240
                               String[] groups, boolean zip,
1241
                               ZipOutputStream zout, boolean withInlineData,
1242
                               Hashtable params)
1243
               throws ClassNotFoundException, IOException, SQLException,
1244
                      McdbException, Exception
1245
  {
1246

    
1247
    try {
1248

    
1249

    
1250
      DocumentImpl doc = new DocumentImpl(docid);
1251

    
1252
      //check the permission for read
1253
      if (!doc.hasReadPermission(user, groups, docid))
1254
      {
1255
        Exception e = new Exception("User " + user + " does not have permission"
1256
                       +" to read the document with the docid " + docid);
1257

    
1258
        throw e;
1259
      }
1260

    
1261
      if ( doc.getRootNodeID() == 0 ) {
1262
        // this is data file
1263
        String filepath = util.getOption("datafilepath");
1264
        if(!filepath.endsWith("/")) {
1265
          filepath += "/";
1266
        }
1267
        String filename = filepath + docid;
1268
        FileInputStream fin = null;
1269
        fin = new FileInputStream(filename);
1270

    
1271
        //MIME type
1272
        String contentType = getServletContext().getMimeType(filename);
1273
        if (contentType == null)
1274
        {
1275
          ContentTypeProvider provider = new ContentTypeProvider(docid);
1276
          contentType = provider.getContentType();
1277
          MetaCatUtil.debugMessage("Final contenttype is: "+ contentType, 30);
1278
        }
1279

    
1280
        response.setContentType(contentType);
1281
        // if we decide to use "application/octet-stream" for all data returns
1282
        // response.setContentType("application/octet-stream");
1283

    
1284
        try {
1285

    
1286
          ServletOutputStream out = response.getOutputStream();
1287
          byte[] buf = new byte[4 * 1024]; // 4K buffer
1288
          int b = fin.read(buf);
1289
          while (b != -1) {
1290
            out.write(buf, 0, b);
1291
            b = fin.read(buf);
1292
          }
1293
        } finally {
1294
          if (fin != null) fin.close();
1295
        }
1296

    
1297
      } else {
1298
        // this is metadata doc
1299
        if ( qformat.equals("xml") ) {
1300

    
1301
          // set content type first
1302
          response.setContentType("text/xml");   //MIME type
1303
          PrintWriter out = response.getWriter();
1304
          doc.toXml(out, user, groups, withInlineData);
1305
        } else {
1306
          response.setContentType("text/html");  //MIME type
1307
          PrintWriter out = response.getWriter();
1308

    
1309
          // Look up the document type
1310
          String doctype = doc.getDoctype();
1311
          // Transform the document to the new doctype
1312
          DBTransform dbt = new DBTransform();
1313
          dbt.transformXMLDocument(doc.toString(user, groups, withInlineData),
1314
                                   doctype,"-//W3C//HTML//EN",
1315
                                   qformat, out, params);
1316
        }
1317

    
1318
      }
1319
    }
1320
    catch (Exception except)
1321
    {
1322
      throw except;
1323

    
1324
    }
1325

    
1326
  }
1327

    
1328
  // read data from URLConnection
1329
  private void readFromURLConnection(HttpServletResponse response, String docid)
1330
               throws IOException, MalformedURLException
1331
  {
1332
    ServletOutputStream out = response.getOutputStream();
1333
    String contentType = getServletContext().getMimeType(docid); //MIME type
1334
    if (contentType == null) {
1335
      if (docid.endsWith(".xml")) {
1336
        contentType="text/xml";
1337
      } else if (docid.endsWith(".css")) {
1338
        contentType="text/css";
1339
      } else if (docid.endsWith(".dtd")) {
1340
        contentType="text/plain";
1341
      } else if (docid.endsWith(".xsd")) {
1342
        contentType="text/xml";
1343
      } else if (docid.endsWith("/")) {
1344
        contentType="text/html";
1345
      } else {
1346
        File f = new File(docid);
1347
        if ( f.isDirectory() ) {
1348
          contentType="text/html";
1349
        } else {
1350
          contentType="application/octet-stream";
1351
        }
1352
      }
1353
    }
1354
    response.setContentType(contentType);
1355
    // if we decide to use "application/octet-stream" for all data returns
1356
    // response.setContentType("application/octet-stream");
1357

    
1358
    // this is http url
1359
    URL url = new URL(docid);
1360
    BufferedInputStream bis = null;
1361
    try {
1362
      bis = new BufferedInputStream(url.openStream());
1363
      byte[] buf = new byte[4 * 1024]; // 4K buffer
1364
      int b = bis.read(buf);
1365
      while (b != -1) {
1366
        out.write(buf, 0, b);
1367
        b = bis.read(buf);
1368
      }
1369
    } finally {
1370
      if (bis != null) bis.close();
1371
    }
1372

    
1373
  }
1374

    
1375
  // read file/doc and write to ZipOutputStream
1376
  private void addDocToZip(String docid, ZipOutputStream zout,
1377
                              String user, String[] groups)
1378
               throws ClassNotFoundException, IOException, SQLException,
1379
                      McdbException, Exception
1380
  {
1381
    byte[] bytestring = null;
1382
    ZipEntry zentry = null;
1383

    
1384
    try {
1385
      URL url = new URL(docid);
1386

    
1387
      // this http url; read from URLConnection; add to zip
1388
      zentry = new ZipEntry(docid);
1389
      zout.putNextEntry(zentry);
1390
      BufferedInputStream bis = null;
1391
      try {
1392
        bis = new BufferedInputStream(url.openStream());
1393
        byte[] buf = new byte[4 * 1024]; // 4K buffer
1394
        int b = bis.read(buf);
1395
        while(b != -1) {
1396
          zout.write(buf, 0, b);
1397
          b = bis.read(buf);
1398
        }
1399
      } finally {
1400
        if (bis != null) bis.close();
1401
      }
1402
      zout.closeEntry();
1403

    
1404
    } catch (MalformedURLException mue) {
1405

    
1406
      // this is metacat doc (data file or metadata doc)
1407

    
1408
      try {
1409

    
1410
        DocumentImpl doc = new DocumentImpl(docid);
1411

    
1412
        //check the permission for read
1413
        if (!doc.hasReadPermission(user, groups, docid))
1414
        {
1415
          Exception e = new Exception("User " + user + " does not have "
1416
                    +"permission to read the document with the docid " + docid);
1417

    
1418
          throw e;
1419
        }
1420

    
1421
        if ( doc.getRootNodeID() == 0 ) {
1422
          // this is data file; add file to zip
1423
          String filepath = util.getOption("datafilepath");
1424
          if(!filepath.endsWith("/")) {
1425
            filepath += "/";
1426
          }
1427
          String filename = filepath + docid;
1428
          FileInputStream fin = null;
1429
          fin = new FileInputStream(filename);
1430
          try {
1431

    
1432
            zentry = new ZipEntry(docid);
1433
            zout.putNextEntry(zentry);
1434
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1435
            int b = fin.read(buf);
1436
            while (b != -1) {
1437
              zout.write(buf, 0, b);
1438
              b = fin.read(buf);
1439
            }
1440
          } finally {
1441
            if (fin != null) fin.close();
1442
          }
1443
          zout.closeEntry();
1444

    
1445
        } else {
1446
          // this is metadata doc; add doc to zip
1447
          bytestring = doc.toString().getBytes();
1448
          zentry = new ZipEntry(docid + ".xml");
1449
          zentry.setSize(bytestring.length);
1450
          zout.putNextEntry(zentry);
1451
          zout.write(bytestring, 0, bytestring.length);
1452
          zout.closeEntry();
1453
        }
1454
      } catch (Exception except) {
1455
        throw except;
1456

    
1457
      }
1458

    
1459
    }
1460

    
1461
  }
1462

    
1463
  // view abstract within document
1464
  private void viewAbstract(HttpServletResponse response,
1465
                            String abstractpath, String docid)
1466
               throws ClassNotFoundException, IOException, SQLException,
1467
                      McdbException, Exception
1468
  {
1469

    
1470
    PrintWriter out =null;
1471
    try {
1472

    
1473
      response.setContentType("text/html");  //MIME type
1474
      out = response.getWriter();
1475
      Object[] abstracts = DBQuery.getNodeContent(abstractpath, docid);
1476
      out.println("<html><head><title>Abstract</title></head>");
1477
      out.println("<body bgcolor=\"white\"><h1>Abstract</h1>");
1478
      for (int i=0; i<abstracts.length; i++) {
1479
        out.println("<p>" + (String)abstracts[i] + "</p>");
1480
      }
1481
      out.println("</body></html>");
1482

    
1483
    } catch (Exception e) {
1484
       out.println("<?xml version=\"1.0\"?>");
1485
       out.println("<error>");
1486
       out.println(e.getMessage());
1487
       out.println("</error>");
1488

    
1489

    
1490
    }
1491
  }
1492
  /**
1493
   * If metacat couldn't find a data file or document locally, it will read this
1494
   * docid from its home server. This is for the replication feature
1495
   */
1496
  private void readFromRemoteMetaCat(HttpServletResponse response, String docid,
1497
                     String rev, String user, String password,
1498
                     ServletOutputStream out, boolean zip, ZipOutputStream zout)
1499
                        throws Exception
1500
 {
1501
   // Create a object of RemoteDocument, "" is for zipEntryPath
1502
   RemoteDocument remoteDoc =
1503
                        new RemoteDocument (docid, rev,user, password, "");
1504
   String docType = remoteDoc.getDocType();
1505
   // Only read data file
1506
   if (docType.equals("BIN"))
1507
   {
1508
    // If it is zip format
1509
    if (zip)
1510
    {
1511
      remoteDoc.readDocumentFromRemoteServerByZip(zout);
1512
    }//if
1513
    else
1514
    {
1515
      if (out == null)
1516
      {
1517
        out = response.getOutputStream();
1518
      }//if
1519
      response.setContentType("application/octet-stream");
1520
      remoteDoc.readDocumentFromRemoteServer(out);
1521
    }//else (not zip)
1522
   }//if doctype=bin
1523
   else
1524
   {
1525
     throw new Exception("Docid: "+docid+"."+rev+" couldn't find");
1526
   }//else
1527
 }//readFromRemoteMetaCat
1528

    
1529
  // END OF READ SECTION
1530

    
1531

    
1532

    
1533
  // INSERT/UPDATE SECTION
1534
  /**
1535
   * Handle the database putdocument request and write an XML document
1536
   * to the database connection
1537
   */
1538
  private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params,
1539
               String user, String[] groups) {
1540

    
1541
    DBConnection dbConn = null;
1542
    int serialNumber = -1;
1543

    
1544
    try {
1545
      // Get the document indicated
1546
      String[] doctext = (String[])params.get("doctext");
1547

    
1548
      String pub = null;
1549
      if (params.containsKey("public")) {
1550
        pub = ((String[])params.get("public"))[0];
1551
      }
1552

    
1553
      StringReader dtd = null;
1554
      if (params.containsKey("dtdtext")) {
1555
        String[] dtdtext = (String[])params.get("dtdtext");
1556
        try {
1557
          if ( !dtdtext[0].equals("") ) {
1558
            dtd = new StringReader(dtdtext[0]);
1559
          }
1560
        } catch (NullPointerException npe) {}
1561
      }
1562

    
1563
      StringReader xml = null;
1564
      boolean validate = false;
1565
      DocumentImplWrapper documentWrapper = null;
1566
      try {
1567
        // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1568
        // in order to decide whether to use validation parser
1569
        validate = needDTDValidation(doctext[0]);
1570
        if (validate)
1571
        {
1572
          // set a dtd base validation parser
1573
          String rule = DocumentImpl.DTD;
1574
          documentWrapper = new DocumentImplWrapper(rule, validate);
1575
        }
1576
        else if (needSchemaValidation(doctext[0]))
1577
        {
1578
          // for eml2
1579
          if (needEml2Validation(doctext[0]))
1580
          {
1581
             // set eml2 base validation parser
1582
            String rule = DocumentImpl.EML2;
1583
            // using emlparser to check id validation
1584
            EMLParser parser = new EMLParser(doctext[0]);
1585
            documentWrapper = new DocumentImplWrapper(rule, true);
1586
          }
1587
          else
1588
          {
1589
            // set schema base validation parser
1590
            String rule = DocumentImpl.SCHEMA;
1591
            documentWrapper = new DocumentImplWrapper(rule, true);
1592
          }
1593
        }
1594
        else
1595
        {
1596
          documentWrapper = new DocumentImplWrapper("", false);
1597
        }
1598

    
1599
        xml = new StringReader(doctext[0]);
1600

    
1601
        String[] action = (String[])params.get("action");
1602
        String[] docid = (String[])params.get("docid");
1603
        String newdocid = null;
1604

    
1605
        String doAction = null;
1606
        if (action[0].equals("insert")) {
1607
          doAction = "INSERT";
1608
        } else if (action[0].equals("update")) {
1609
          doAction = "UPDATE";
1610
        }
1611

    
1612
        try
1613
        {
1614
          // get a connection from the pool
1615
          dbConn=DBConnectionPool.
1616
                  getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1617
          serialNumber=dbConn.getCheckOutSerialNumber();
1618

    
1619

    
1620
          // write the document to the database
1621
          try
1622
          {
1623
            String accNumber = docid[0];
1624
            MetaCatUtil.debugMessage(""+ doAction + " " + accNumber +"...", 10);
1625
            if (accNumber.equals(""))
1626
            {
1627
              accNumber = null;
1628
            }//if
1629
            newdocid = documentWrapper.write(dbConn, xml, pub, dtd, doAction,
1630
                                          accNumber, user, groups);
1631

    
1632
          }//try
1633
          catch (NullPointerException npe)
1634
          {
1635
            newdocid = documentWrapper.write(dbConn, xml, pub, dtd, doAction,
1636
                                          null, user, groups);
1637
          }//catch
1638

    
1639
        }//try
1640
        finally
1641
        {
1642
          // Return db connection
1643
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1644
        }
1645

    
1646
        // set content type and other response header fields first
1647
        //response.setContentType("text/xml");
1648
        out.println("<?xml version=\"1.0\"?>");
1649
        out.println("<success>");
1650
        out.println("<docid>" + newdocid + "</docid>");
1651
        out.println("</success>");
1652

    
1653
      }
1654
      catch (NullPointerException npe)
1655
      {
1656
        //response.setContentType("text/xml");
1657
        out.println("<?xml version=\"1.0\"?>");
1658
        out.println("<error>");
1659
        out.println(npe.getMessage());
1660
        out.println("</error>");
1661
      }
1662
    }
1663
    catch (Exception e)
1664
    {
1665
      //response.setContentType("text/xml");
1666
      out.println("<?xml version=\"1.0\"?>");
1667
      out.println("<error>");
1668
      out.println(e.getMessage());
1669
      out.println("</error>");
1670
    }
1671
  }
1672

    
1673
  /**
1674
   * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1675
   * in order to decide whether to use validation parser
1676
   */
1677
  private static boolean needDTDValidation(String xmltext) throws IOException {
1678

    
1679
    StringReader xmlreader = new StringReader(xmltext);
1680
    StringBuffer cbuff = new StringBuffer();
1681
    java.util.Stack st = new java.util.Stack();
1682
    boolean validate = false;
1683
    int c;
1684
    int inx;
1685

    
1686
    // read from the stream until find the keywords
1687
    while ( (st.empty() || st.size()<4) && ((c = xmlreader.read()) != -1) ) {
1688
      cbuff.append((char)c);
1689

    
1690
      // "<!DOCTYPE" keyword is found; put it in the stack
1691
      if ( (inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1 ) {
1692
        cbuff = new StringBuffer();
1693
        st.push("<!DOCTYPE");
1694
      }
1695
      // "PUBLIC" keyword is found; put it in the stack
1696
      if ( (inx = cbuff.toString().indexOf("PUBLIC")) != -1 ) {
1697
        cbuff = new StringBuffer();
1698
        st.push("PUBLIC");
1699
      }
1700
      // "SYSTEM" keyword is found; put it in the stack
1701
      if ( (inx = cbuff.toString().indexOf("SYSTEM")) != -1 ) {
1702
        cbuff = new StringBuffer();
1703
        st.push("SYSTEM");
1704
      }
1705
      // ">" character is found; put it in the stack
1706
      // ">" is found twice: fisrt from <?xml ...?>
1707
      // and second from <!DOCTYPE ... >
1708
      if ( (inx = cbuff.toString().indexOf(">")) != -1 ) {
1709
        cbuff = new StringBuffer();
1710
        st.push(">");
1711
      }
1712
    }
1713

    
1714
    // close the stream
1715
    xmlreader.close();
1716

    
1717
    // check the stack whether it contains the keywords:
1718
    // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1719
    if ( st.size() == 4 ) {
1720
      if ( ((String)st.pop()).equals(">") &&
1721
           ( ((String)st.peek()).equals("PUBLIC") |
1722
             ((String)st.pop()).equals("SYSTEM") ) &&
1723
           ((String)st.pop()).equals("<!DOCTYPE") )  {
1724
        validate = true;
1725
      }
1726
    }
1727

    
1728
    MetaCatUtil.debugMessage("Validation for dtd is " + validate, 10);
1729
    return validate;
1730
  }
1731
  // END OF INSERT/UPDATE SECTION
1732

    
1733
  /* check if the xml string contains key words to specify schema loocation*/
1734
  private boolean needSchemaValidation(String xml)
1735
  {
1736
    boolean needSchemaValidate =false;
1737
    if (xml == null)
1738
    {
1739
      MetaCatUtil.debugMessage("Validation for schema is " +
1740
                               needSchemaValidate, 10);
1741
      return needSchemaValidate;
1742
    }
1743
    String targetLine = getSchemaLine(xml);
1744
    // to see if the second line contain some keywords
1745
    if (targetLine != null && (targetLine.indexOf(SCHEMALOCATIONKEYWORD) != -1||
1746
             targetLine.indexOf(NONAMESPACELOCATION) != -1 ))
1747
    {
1748
      // if contains schema location key word, should be validate
1749
      needSchemaValidate = true;
1750
    }
1751

    
1752
    MetaCatUtil.debugMessage("Validation for schema is " +
1753
                             needSchemaValidate, 10);
1754
    return needSchemaValidate;
1755

    
1756
  }
1757

    
1758
   /* check if the xml string contains key words to specify schema loocation*/
1759
  private boolean needEml2Validation(String xml)
1760
  {
1761
    boolean needEml2Validate =false;
1762
    String emlNameSpace = "=\""+DocumentImpl.EMLNAMESPACE+"\"";
1763
    if (xml == null)
1764
    {
1765
      MetaCatUtil.debugMessage("Validation for schema is " +
1766
                               needEml2Validate, 10);
1767
      return needEml2Validate;
1768
    }
1769
    String targetLine = getSchemaLine(xml);
1770

    
1771
    if (targetLine != null && targetLine.indexOf(EML2KEYWORD) != -1 &&
1772
        targetLine.indexOf(emlNameSpace) != -1)
1773
    {
1774
      // if contains schema location key word, should be validate
1775
      needEml2Validate = true;
1776
    }
1777

    
1778
    MetaCatUtil.debugMessage("Validation for eml is " +
1779
                             needEml2Validate, 10);
1780
    return needEml2Validate;
1781

    
1782
  }
1783

    
1784
  private String getSchemaLine(String xml)
1785
  {
1786
    // find the line
1787
    String secondLine = null;
1788
    int count =0;
1789
    int endIndex = 0;
1790
    int startIndex = 0;
1791
    final int TARGETNUM = 2;
1792
    for (int i=0; i<xml.length(); i++)
1793
    {
1794
      // didn't count comment
1795
      if (xml.charAt(i) =='<' && xml.charAt(i+1) != '!')
1796
      {
1797
        count ++;
1798
        //find start index
1799
        if (count == TARGETNUM)
1800
        {
1801
          startIndex = i;
1802
        }
1803
      }//if
1804
      // find the end index
1805
      if (count== TARGETNUM && xml.charAt(i) =='>')
1806
      {
1807
        endIndex = i;
1808
        break;
1809
      }//if
1810
    }//for
1811
    // get the second line string
1812
    MetaCatUtil.debugMessage("The start index for second line: "+startIndex, 25);
1813
    MetaCatUtil.debugMessage("The end index for second line: "+endIndex, 25);
1814
    if (startIndex != 0 && endIndex != 0)
1815
    {
1816
      secondLine = xml.substring(startIndex+1, endIndex);
1817

    
1818
    }//if
1819
    MetaCatUtil.debugMessage("the second line string is: "+secondLine, 25);
1820
    return secondLine;
1821
  }
1822

    
1823
  // DELETE SECTION
1824
  /**
1825
   * Handle the database delete request and delete an XML document
1826
   * from the database connection
1827
   */
1828
  private void handleDeleteAction(PrintWriter out, Hashtable params,
1829
               HttpServletResponse response, String user, String[] groups) {
1830

    
1831
    String[] docid = (String[])params.get("docid");
1832

    
1833
    // delete the document from the database
1834
    try {
1835

    
1836
                                      // NOTE -- NEED TO TEST HERE
1837
                                      // FOR EXISTENCE OF DOCID PARAM
1838
                                      // BEFORE ACCESSING ARRAY
1839
      try {
1840
        DocumentImpl.delete(docid[0], user, groups);
1841
        response.setContentType("text/xml");
1842
        out.println("<?xml version=\"1.0\"?>");
1843
        out.println("<success>");
1844
        out.println("Document deleted.");
1845
        out.println("</success>");
1846
      } catch (AccessionNumberException ane) {
1847
        response.setContentType("text/xml");
1848
        out.println("<?xml version=\"1.0\"?>");
1849
        out.println("<error>");
1850
        out.println("Error deleting document!!!");
1851
        out.println(ane.getMessage());
1852
        out.println("</error>");
1853
      }
1854
    } catch (Exception e) {
1855
      response.setContentType("text/xml");
1856
      out.println("<?xml version=\"1.0\"?>");
1857
      out.println("<error>");
1858
      out.println(e.getMessage());
1859
      out.println("</error>");
1860
    }
1861
  }
1862
  // END OF DELETE SECTION
1863

    
1864
  // VALIDATE SECTION
1865
  /**
1866
   * Handle the validation request and return the results to the requestor
1867
   */
1868
  private void handleValidateAction(PrintWriter out, Hashtable params) {
1869

    
1870
    // Get the document indicated
1871
    String valtext = null;
1872
    DBConnection dbConn = null;
1873
    int serialNumber = -1;
1874

    
1875
    try {
1876
      valtext = ((String[])params.get("valtext"))[0];
1877
    } catch (Exception nullpe) {
1878

    
1879

    
1880
      String docid = null;
1881
      try {
1882
        // Find the document id number
1883
        docid = ((String[])params.get("docid"))[0];
1884

    
1885

    
1886
        // Get the document indicated from the db
1887
        DocumentImpl xmldoc = new DocumentImpl(docid);
1888
        valtext = xmldoc.toString();
1889

    
1890
      } catch (NullPointerException npe) {
1891

    
1892
        out.println("<error>Error getting document ID: " + docid + "</error>");
1893
        //if ( conn != null ) { util.returnConnection(conn); }
1894
        return;
1895
      } catch (Exception e) {
1896

    
1897
        out.println(e.getMessage());
1898
      }
1899
    }
1900

    
1901

    
1902
    try {
1903
      // get a connection from the pool
1904
      dbConn=DBConnectionPool.
1905
                  getDBConnection("MetaCatServlet.handleValidateAction");
1906
      serialNumber=dbConn.getCheckOutSerialNumber();
1907
      DBValidate valobj = new DBValidate(saxparser,dbConn);
1908
      boolean valid = valobj.validateString(valtext);
1909

    
1910
      // set content type and other response header fields first
1911

    
1912
      out.println(valobj.returnErrors());
1913

    
1914
    } catch (NullPointerException npe2) {
1915
      // set content type and other response header fields first
1916

    
1917
      out.println("<error>Error validating document.</error>");
1918
    } catch (Exception e) {
1919

    
1920
      out.println(e.getMessage());
1921
    } finally {
1922
      // Return db connection
1923
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1924
    }
1925
  }
1926
  // END OF VALIDATE SECTION
1927

    
1928
  // OTHER ACTION HANDLERS
1929

    
1930
  /**
1931
   * Handle "getrevsionanddoctype" action
1932
   * Given a docid, return it's current revision and doctype from data base
1933
   * The output is String look like "rev;doctype"
1934
   */
1935
  private void handleGetRevisionAndDocTypeAction(PrintWriter out,
1936
                                                              Hashtable params)
1937
  {
1938
    // To store doc parameter
1939
    String [] docs = new String[10];
1940
    // Store a single doc id
1941
    String givenDocId = null;
1942
    // Get docid from parameters
1943
    if (params.containsKey("docid"))
1944
    {
1945
      docs = (String[])params.get("docid");
1946
    }
1947
    // Get first docid form string array
1948
    givenDocId = docs[0];
1949

    
1950
    try
1951
    {
1952
      // Make sure there is a docid
1953
      if (givenDocId == null || givenDocId.equals(""))
1954
      {
1955
        throw new Exception("User didn't specify docid!");
1956
      }//if
1957

    
1958
      // Create a DBUtil object
1959
      DBUtil dbutil = new DBUtil();
1960
      // Get a rev and doctype
1961
      String revAndDocType =
1962
                dbutil.getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
1963
      out.println(revAndDocType);
1964

    
1965
    }//try
1966
    catch (Exception e)
1967
    {
1968
      // Handle exception
1969
      out.println("<?xml version=\"1.0\"?>");
1970
      out.println("<error>");
1971
      out.println(e.getMessage());
1972
      out.println("</error>");
1973
    }//catch
1974

    
1975
  }//handleGetRevisionAndDocTypeAction
1976

    
1977
  /**
1978
   * Handle "getaccesscontrol" action.
1979
   * Read Access Control List from db connection in XML format
1980
   */
1981
  private void handleGetAccessControlAction(PrintWriter out, Hashtable params,
1982
                                       HttpServletResponse response,
1983
                                       String username, String[] groupnames) {
1984

    
1985
    DBConnection dbConn = null;
1986
    int serialNumber = -1;
1987
    String docid = ((String[])params.get("docid"))[0];
1988

    
1989
    try {
1990

    
1991
        // get connection from the pool
1992
        dbConn=DBConnectionPool.
1993
                 getDBConnection("MetaCatServlet.handleGetAccessControlAction");
1994
        serialNumber=dbConn.getCheckOutSerialNumber();
1995
        AccessControlList aclobj = new AccessControlList(dbConn);
1996
        String acltext = aclobj.getACL(docid, username, groupnames);
1997
        out.println(acltext);
1998

    
1999
    } catch (Exception e) {
2000
      out.println("<?xml version=\"1.0\"?>");
2001
      out.println("<error>");
2002
      out.println(e.getMessage());
2003
      out.println("</error>");
2004
    } finally {
2005
      // Retrun db connection to pool
2006
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2007
    }
2008

    
2009
  }
2010

    
2011
  /**
2012
   * Handle the "getprincipals" action.
2013
   * Read all principals from authentication scheme in XML format
2014
   */
2015
  private void handleGetPrincipalsAction(PrintWriter out, String user,
2016
                                         String password) {
2017

    
2018

    
2019
    try {
2020

    
2021

    
2022
        AuthSession auth = new AuthSession();
2023
        String principals = auth.getPrincipals(user, password);
2024
        out.println(principals);
2025

    
2026
    } catch (Exception e) {
2027
      out.println("<?xml version=\"1.0\"?>");
2028
      out.println("<error>");
2029
      out.println(e.getMessage());
2030
      out.println("</error>");
2031
    }
2032

    
2033
  }
2034

    
2035
  /**
2036
   * Handle "getdoctypes" action.
2037
   * Read all doctypes from db connection in XML format
2038
   */
2039
  private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
2040
                                       HttpServletResponse response) {
2041

    
2042

    
2043
    try {
2044

    
2045

    
2046
        DBUtil dbutil = new DBUtil();
2047
        String doctypes = dbutil.readDoctypes();
2048
        out.println(doctypes);
2049

    
2050
    } catch (Exception e) {
2051
      out.println("<?xml version=\"1.0\"?>");
2052
      out.println("<error>");
2053
      out.println(e.getMessage());
2054
      out.println("</error>");
2055
    }
2056

    
2057
  }
2058

    
2059
  /**
2060
   * Handle the "getdtdschema" action.
2061
   * Read DTD or Schema file for a given doctype from Metacat catalog system
2062
   */
2063
  private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
2064
                                        HttpServletResponse response) {
2065

    
2066

    
2067
    String doctype = null;
2068
    String[] doctypeArr = (String[])params.get("doctype");
2069

    
2070
    // get only the first doctype specified in the list of doctypes
2071
    // it could be done for all doctypes in that list
2072
    if (doctypeArr != null) {
2073
        doctype = ((String[])params.get("doctype"))[0];
2074
    }
2075

    
2076
    try {
2077

    
2078

    
2079
        DBUtil dbutil = new DBUtil();
2080
        String dtdschema = dbutil.readDTDSchema(doctype);
2081
        out.println(dtdschema);
2082

    
2083
    } catch (Exception e) {
2084
      out.println("<?xml version=\"1.0\"?>");
2085
      out.println("<error>");
2086
      out.println(e.getMessage());
2087
      out.println("</error>");
2088
    }
2089

    
2090
  }
2091

    
2092
  /**
2093
   * Handle the "getdataguide" action.
2094
   * Read Data Guide for a given doctype from db connection in XML format
2095
   */
2096
  private void handleGetDataGuideAction(PrintWriter out, Hashtable params,
2097
                                        HttpServletResponse response) {
2098

    
2099

    
2100
    String doctype = null;
2101
    String[] doctypeArr = (String[])params.get("doctype");
2102

    
2103
    // get only the first doctype specified in the list of doctypes
2104
    // it could be done for all doctypes in that list
2105
    if (doctypeArr != null) {
2106
        doctype = ((String[])params.get("doctype"))[0];
2107
    }
2108

    
2109
    try {
2110

    
2111

    
2112
        DBUtil dbutil = new DBUtil();
2113
        String dataguide = dbutil.readDataGuide(doctype);
2114
        out.println(dataguide);
2115

    
2116
    } catch (Exception e) {
2117
      out.println("<?xml version=\"1.0\"?>");
2118
      out.println("<error>");
2119
      out.println(e.getMessage());
2120
      out.println("</error>");
2121
    }
2122

    
2123
  }
2124

    
2125
  /**
2126
   * Handle the "getlastdocid" action.
2127
   * Get the latest docid with rev number from db connection in XML format
2128
   */
2129
  private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
2130
                                        HttpServletResponse response) {
2131

    
2132

    
2133
    String scope = ((String[])params.get("scope"))[0];
2134
    if (scope == null) {
2135
        scope = ((String[])params.get("username"))[0];
2136
    }
2137

    
2138
    try {
2139

    
2140

    
2141
        DBUtil dbutil = new DBUtil();
2142
        String lastDocid = dbutil.getMaxDocid(scope);
2143
        out.println("<?xml version=\"1.0\"?>");
2144
        out.println("<lastDocid>");
2145
        out.println("  <scope>" + scope + "</scope>");
2146
        out.println("  <docid>" + lastDocid + "</docid>");
2147
        out.println("</lastDocid>");
2148

    
2149
    } catch (Exception e) {
2150
      out.println("<?xml version=\"1.0\"?>");
2151
      out.println("<error>");
2152
      out.println(e.getMessage());
2153
      out.println("</error>");
2154
    }
2155

    
2156
  }
2157

    
2158
  /**
2159
   * Handle documents passed to metacat that are encoded using the
2160
   * "multipart/form-data" mime type.  This is typically used for uploading
2161
   * data files which may be binary and large.
2162
   */
2163
  private void handleMultipartForm(HttpServletRequest request,
2164
                                   HttpServletResponse response)
2165
  {
2166
    PrintWriter out = null;
2167
    String action = null;
2168

    
2169
    // Parse the multipart form, and save the parameters in a Hashtable and
2170
    // save the FileParts in a hashtable
2171

    
2172
    Hashtable params = new Hashtable();
2173
    Hashtable fileList = new Hashtable();
2174
    int sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit")))
2175
                                                                   .intValue();
2176
    MetaCatUtil.debugMessage("The limit size of data file is: "+sizeLimit, 50);
2177

    
2178
    try {
2179
      // MBJ: need to put filesize limit in Metacat config (metacat.properties)
2180
      MultipartParser mp = new MultipartParser(request, sizeLimit*1024*1024);
2181
      Part part;
2182
      while ((part = mp.readNextPart()) != null) {
2183
        String name = part.getName();
2184

    
2185
        if (part.isParam()) {
2186
          // it's a parameter part
2187
          ParamPart paramPart = (ParamPart) part;
2188
          String value = paramPart.getStringValue();
2189
          params.put(name, value);
2190
          if (name.equals("action")) {
2191
            action = value;
2192
          }
2193
        } else if (part.isFile()) {
2194
          // it's a file part
2195
          FilePart filePart = (FilePart) part;
2196
          fileList.put(name, filePart);
2197

    
2198
          // Stop once the first file part is found, otherwise going onto the
2199
          // next part prevents access to the file contents.  So...for upload
2200
          // to work, the datafile must be the last part
2201
          break;
2202
        }
2203
      }
2204
    } catch (IOException ioe) {
2205
      try {
2206
        out = response.getWriter();
2207
      } catch (IOException ioe2) {
2208
        System.err.println("Fatal Error: couldn't get response output stream.");
2209
      }
2210
      out.println("<?xml version=\"1.0\"?>");
2211
      out.println("<error>");
2212
      out.println("Error: problem reading multipart data.");
2213
      out.println("</error>");
2214
    }
2215

    
2216
    // Get the session information
2217
    String username = null;
2218
    String password = null;
2219
    String[] groupnames = null;
2220
    String sess_id = null;
2221

    
2222
    // be aware of session expiration on every request
2223
    HttpSession sess = request.getSession(true);
2224
    if (sess.isNew()) {
2225
      // session expired or has not been stored b/w user requests
2226
      username = "public";
2227
      sess.setAttribute("username", username);
2228
    } else {
2229
      username = (String)sess.getAttribute("username");
2230
      password = (String)sess.getAttribute("password");
2231
      groupnames = (String[])sess.getAttribute("groupnames");
2232
      try {
2233
        sess_id = (String)sess.getId();
2234
      } catch(IllegalStateException ise) {
2235
        System.out.println("error in  handleMultipartForm: this shouldn't " +
2236
                           "happen: the session should be valid: " +
2237
                           ise.getMessage());
2238
      }
2239
    }
2240

    
2241
    // Get the out stream
2242
    try {
2243
          out = response.getWriter();
2244
        } catch (IOException ioe2) {
2245
          util.debugMessage("Fatal Error: couldn't get response "+
2246
                             "output stream.", 30);
2247
        }
2248

    
2249
    if ( action.equals("upload")) {
2250
      if (username != null &&  !username.equals("public")) {
2251
        handleUploadAction(request, out, params, fileList,
2252
                           username, groupnames);
2253
      } else {
2254

    
2255
        out.println("<?xml version=\"1.0\"?>");
2256
        out.println("<error>");
2257
        out.println("Permission denied for " + action);
2258
        out.println("</error>");
2259
      }
2260
    } else {
2261
      /*try {
2262
        out = response.getWriter();
2263
      } catch (IOException ioe2) {
2264
        System.err.println("Fatal Error: couldn't get response output stream.");
2265
      }*/
2266
      out.println("<?xml version=\"1.0\"?>");
2267
      out.println("<error>");
2268
      out.println("Error: action not registered.  Please report this error.");
2269
      out.println("</error>");
2270
    }
2271
    out.close();
2272
  }
2273

    
2274
  /**
2275
   * Handle the upload action by saving the attached file to disk and
2276
   * registering it in the Metacat db
2277
   */
2278
  private void handleUploadAction(HttpServletRequest request,
2279
                                  PrintWriter out,
2280
                                  Hashtable params, Hashtable fileList,
2281
                                  String username, String[] groupnames)
2282
  {
2283
    //PrintWriter out = null;
2284
    //Connection conn = null;
2285
    String action = null;
2286
    String docid = null;
2287

    
2288
    /*response.setContentType("text/xml");
2289
    try
2290
    {
2291
      out = response.getWriter();
2292
    }
2293
    catch (IOException ioe2)
2294
    {
2295
      System.err.println("Fatal Error: couldn't get response output stream.");
2296
    }*/
2297

    
2298
    if (params.containsKey("docid"))
2299
    {
2300
      docid = (String)params.get("docid");
2301
    }
2302

    
2303
    // Make sure we have a docid and datafile
2304
    if (docid != null && fileList.containsKey("datafile")) {
2305

    
2306
      // Get a reference to the file part of the form
2307
      FilePart filePart = (FilePart)fileList.get("datafile");
2308
      String fileName = filePart.getFileName();
2309
      MetaCatUtil.debugMessage("Uploading filename: " + fileName, 10);
2310

    
2311
      // Check if the right file existed in the uploaded data
2312
      if (fileName != null) {
2313

    
2314
        try
2315
        {
2316
           //MetaCatUtil.debugMessage("Upload datafile " + docid +"...", 10);
2317
           //If document get lock data file grant
2318
           if (DocumentImpl.getDataFileLockGrant(docid))
2319
           {
2320
              // register the file in the database (which generates an exception
2321
              //if the docid is not acceptable or other untoward things happen
2322
              DocumentImpl.registerDocument(fileName, "BIN", docid, username);
2323

    
2324
              // Save the data file to disk using "docid" as the name
2325
              dataDirectory.mkdirs();
2326
              File newFile = new File(dataDirectory, docid);
2327
              long size = filePart.writeTo(newFile);
2328

    
2329
              // Force replication this data file
2330
              // To data file, "insert" and update is same
2331
              // The fourth parameter is null. Because it is notification server
2332
              // and this method is in MetaCatServerlet. It is original command,
2333
              // not get force replication info from another metacat
2334
              ForceReplicationHandler frh = new ForceReplicationHandler
2335
                                                (docid, "insert", false, null);
2336

    
2337
              // set content type and other response header fields first
2338
              out.println("<?xml version=\"1.0\"?>");
2339
              out.println("<success>");
2340
              out.println("<docid>" + docid + "</docid>");
2341
              out.println("<size>" + size + "</size>");
2342
              out.println("</success>");
2343
          }//if
2344

    
2345
        } //try
2346
        catch (Exception e)
2347
        {
2348
          out.println("<?xml version=\"1.0\"?>");
2349
          out.println("<error>");
2350
          out.println(e.getMessage());
2351
          out.println("</error>");
2352
        }
2353

    
2354
      }
2355
      else
2356
      {
2357
        // the field did not contain a file
2358
        out.println("<?xml version=\"1.0\"?>");
2359
        out.println("<error>");
2360
        out.println("The uploaded data did not contain a valid file.");
2361
        out.println("</error>");
2362
      }
2363
    }
2364
    else
2365
    {
2366
      // Error bcse docid missing or file missing
2367
      out.println("<?xml version=\"1.0\"?>");
2368
      out.println("<error>");
2369
      out.println("The uploaded data did not contain a valid docid " +
2370
                  "or valid file.");
2371
      out.println("</error>");
2372
    }
2373
  }
2374

    
2375
  /*
2376
   * A method to handle set access action
2377
   */
2378
  private void handleSetAccessAction(PrintWriter out,
2379
                                   Hashtable params,
2380
                                   String username)
2381
  {
2382
    String [] docList        = null;
2383
    String [] principalList  = null;
2384
    String [] permissionList = null;
2385
    String [] permTypeList   = null;
2386
    String [] permOrderList  = null;
2387
    String permission = null;
2388
    String permType   = null;
2389
    String permOrder  = null;
2390
    Vector errorList  = new Vector();
2391
    String error      = null;
2392
    Vector successList = new Vector();
2393
    String success    = null;
2394

    
2395

    
2396
    // Get parameters
2397
    if (params.containsKey("docid"))
2398
    {
2399
      docList = (String[])params.get("docid");
2400
    }
2401
    if (params.containsKey("principal"))
2402
    {
2403
      principalList = (String[])params.get("principal");
2404
    }
2405
    if (params.containsKey("permission"))
2406
    {
2407
      permissionList = (String[])params.get("permission");
2408

    
2409
    }
2410
    if (params.containsKey("permType"))
2411
    {
2412
      permTypeList = (String[])params.get("permType");
2413

    
2414
    }
2415
    if (params.containsKey("permOrder"))
2416
    {
2417
      permOrderList = (String[])params.get("permOrder");
2418

    
2419
    }
2420

    
2421
    // Make sure the parameter is not null
2422
    if (docList == null || principalList == null || permTypeList == null ||
2423
        permissionList == null)
2424
    {
2425
      error = "Please check your parameter list, it should look like: "+
2426
              "?action=setaccess&docid=pipeline.1.1&principal=public" +
2427
              "&permission=read&permType=allow&permOrder=allowFirst";
2428
      errorList.addElement(error);
2429
      outputResponse(successList, errorList, out);
2430
      return;
2431
    }
2432

    
2433
    // Only select first element for permission, type and order
2434
    permission = permissionList[0];
2435
    permType = permTypeList[0];
2436
    if (permOrderList != null)
2437
    {
2438
       permOrder = permOrderList[0];
2439
    }
2440

    
2441
    // Get package doctype set
2442
    Vector packageSet =MetaCatUtil.getOptionList(
2443
                                    MetaCatUtil.getOption("packagedoctypeset"));
2444
    //debug
2445
    if (packageSet != null)
2446
    {
2447
      for (int i = 0; i<packageSet.size(); i++)
2448
      {
2449
        MetaCatUtil.debugMessage("doctype in package set: " +
2450
                              (String)packageSet.elementAt(i), 34);
2451
      }
2452
    }//if
2453

    
2454
    // handle every accessionNumber
2455
    for (int i=0; i <docList.length; i++)
2456
    {
2457
      String accessionNumber = docList[i];
2458
      String owner = null;
2459
      String publicId = null;
2460
      // Get document owner and public id
2461
      try
2462
      {
2463
        owner = getFieldValueForDoc(accessionNumber, "user_owner");
2464
        publicId = getFieldValueForDoc(accessionNumber, "doctype");
2465
      }//try
2466
      catch (Exception e)
2467
      {
2468
        MetaCatUtil.debugMessage("Error in handleSetAccessAction: " +
2469
                                  e.getMessage(), 30);
2470
        error = "Error in set access control for document - " + accessionNumber+
2471
                 e.getMessage();
2472
        errorList.addElement(error);
2473
        continue;
2474
      }
2475
      //check if user is the owner. Only owner can do owner
2476
      if (username == null || owner == null || !username.equals(owner))
2477
      {
2478
        error = "User - " + username + " does not have permission to set " +
2479
                "access control for docid - " + accessionNumber;
2480
        errorList.addElement(error);
2481
        continue;
2482
      }
2483

    
2484
      // If docid publicid is BIN data file or other beta4, 6 package document
2485
      // we could not do set access control. Because we don't want inconsistent
2486
      // to its access docuemnt
2487
      if (publicId!=null && packageSet!=null && packageSet.contains(publicId))
2488
      {
2489
        error = "Could not set access control to document "+ accessionNumber +
2490
                "because it is in a pakcage and it has a access file for it";
2491
        errorList.addElement(error);
2492
        continue;
2493
      }
2494

    
2495
      // for every principle
2496
      for (int j = 0; j<principalList.length; j++)
2497
      {
2498
        String principal = principalList[j];
2499
        try
2500
        {
2501
          //insert permission
2502
          AccessControlForSingleFile accessControl = new
2503
                           AccessControlForSingleFile(accessionNumber,
2504
                                    principal, permission, permType, permOrder);
2505
          accessControl.insertPermissions();
2506
          success = "Set access control to document "+ accessionNumber +
2507
                    " successfully";
2508
          successList.addElement(success);
2509
        }
2510
        catch (Exception ee)
2511
        {
2512
          MetaCatUtil.debugMessage("Erorr in handleSetAccessAction2: " +
2513
                                   ee.getMessage(), 30);
2514
          error = "Faild to set access control for document " +
2515
                  accessionNumber + " because " + ee.getMessage();
2516
          errorList.addElement(error);
2517
          continue;
2518
        }
2519
      }//for every principle
2520
    }//for every document
2521
    outputResponse(successList, errorList, out);
2522
  }//handleSetAccessAction
2523

    
2524

    
2525
  /*
2526
   * A method try to determin a docid's public id, if couldn't find null
2527
   * will be returned.
2528
   */
2529
  private String getFieldValueForDoc(String accessionNumber, String fieldName)
2530
                                      throws Exception
2531
  {
2532
    if (accessionNumber==null || accessionNumber.equals("") ||fieldName == null
2533
        || fieldName.equals(""))
2534
    {
2535
      throw new Exception("Docid or field name was not specified");
2536
    }
2537

    
2538
    PreparedStatement pstmt = null;
2539
    ResultSet rs = null;
2540
    String fieldValue = null;
2541
    String docId = null;
2542
    DBConnection conn = null;
2543
    int serialNumber = -1;
2544

    
2545
    // get rid of revision if access number has
2546
    docId = MetaCatUtil.getDocIdFromString(accessionNumber);
2547
    try
2548
    {
2549
      //check out DBConnection
2550
      conn=DBConnectionPool.getDBConnection("MetaCatServlet.getPublicIdForDoc");
2551
      serialNumber=conn.getCheckOutSerialNumber();
2552
      pstmt = conn.prepareStatement(
2553
            "SELECT " + fieldName + " FROM xml_documents " +
2554
            "WHERE docid = ? ");
2555

    
2556
      pstmt.setString(1, docId);
2557
      pstmt.execute();
2558
      rs = pstmt.getResultSet();
2559
      boolean hasRow = rs.next();
2560
      int perm = 0;
2561
      if ( hasRow )
2562
      {
2563
        fieldValue = rs.getString(1);
2564
      }
2565
      else
2566
      {
2567
        throw new Exception("Could not find document: "+accessionNumber);
2568
      }
2569
    }//try
2570
    catch (Exception e)
2571
    {
2572
      MetaCatUtil.debugMessage("Exception in MetacatServlet.getPublicIdForDoc: "
2573
                               + e.getMessage(), 30);
2574
      throw e;
2575
    }
2576
    finally
2577
    {
2578
      try
2579
      {
2580
        rs.close();
2581
        pstmt.close();
2582

    
2583
      }
2584
      finally
2585
      {
2586
        DBConnectionPool.returnDBConnection(conn, serialNumber);
2587
      }
2588
    }
2589
    return fieldValue;
2590
  }//getFieldValueForDoc
2591

    
2592
  /*
2593
   * A method to output setAccess action result
2594
   */
2595
  private void outputResponse(Vector successList,
2596
                              Vector errorList,
2597
                              PrintWriter out)
2598
  {
2599
    boolean error = false;
2600
    boolean success = false;
2601
    // Output prolog
2602
    out.println(PROLOG);
2603
    // output success message
2604
    if ( successList != null)
2605
    {
2606
      for (int i = 0; i<successList.size(); i++)
2607
      {
2608
        out.println(SUCCESS);
2609
        out.println((String)successList.elementAt(i));
2610
        out.println(SUCCESSCLOSE);
2611
        success = true;
2612
      }//for
2613
    }//if
2614
    // output error message
2615
    if (errorList != null)
2616
    {
2617
      for (int i = 0; i<errorList.size(); i++)
2618
      {
2619
        out.println(ERROR);
2620
        out.println((String)errorList.elementAt(i));
2621
        out.println(ERRORCLOSE);
2622
        error = true;
2623
      }//for
2624
    }//if
2625

    
2626
    // if no error and no success info, send a error that nothing happened
2627
    if( !error && !success)
2628
    {
2629
      out.println(ERROR);
2630
      out.println("Nothing happend for setaccess action");
2631
      out.println(ERRORCLOSE);
2632
    }
2633

    
2634
  }//outputResponse
2635
}
(40-40/57)