Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements a metadata catalog as a java Servlet
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Matt Jones, Dan Higgins, Jivka Bojilova, Chad Berkley
7
 *    Release: @release@
8
 *
9
 *   '$Author: tao $'
10
 *     '$Date: 2003-11-18 16:51:56 -0800 (Tue, 18 Nov 2003) $'
11
 * '$Revision: 1906 $'
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 Hashtable sessionHash = new Hashtable();
122
  private static final String PROLOG = "<?xml version=\"1.0\"?>";
123
  private static final String SUCCESS = "<success>";
124
  private static final String SUCCESSCLOSE = "</success>";
125
  private static final String ERROR = "<error>";
126
  private static final String ERRORCLOSE = "</error>";
127
  public static final String SCHEMALOCATIONKEYWORD = ":schemaLocation";
128
  public static final String NONAMESPACELOCATION = ":noNamespaceSchemaLocation";
129
  public static final String EML2KEYWORD =":eml";
130

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

    
141
      util = new MetaCatUtil();
142

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

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

    
155

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

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

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

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

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

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

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

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

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

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

    
217

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

    
224

    
225
      while (paramlist.hasMoreElements()) {
226

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

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

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

    
243

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

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

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

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

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

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

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

    
330
          username = (String)sess.getAttribute("username");
331
          password = (String)sess.getAttribute("password");
332
          groupnames = (String[])sess.getAttribute("groupnames");
333
        }
334
      }
335
      
336
      //make user user username should be public
337
      if (username == null || (username.trim().equals("")))
338
      {
339
        username = "public";
340
      }
341

    
342
       // Now that we know the session is valid, we can delegate the request
343
      // to a particular action handler
344
      if(action.equals("query")) {
345
        PrintWriter out = response.getWriter();
346
        handleQuery(out,params,response,username,groupnames,sess_id);
347
        out.close();
348
      } else if(action.equals("squery")) {
349
        PrintWriter out = response.getWriter();
350
        if(params.containsKey("query")) {
351
         handleSQuery(out, params,response,username,groupnames,sess_id);
352
         out.close();
353
        } else {
354
          out.println("Illegal action squery without \"query\" parameter");
355
          out.close();
356
        }
357
      } else if (action.equals("export")) {
358

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

    
468
      //util.closeConnections();
469
      // Close the stream to the client
470
      //out.close();
471
    }
472
  }
473

    
474
  // LOGIN & LOGOUT SECTION
475
  /**
476
   * Handle the login request. Create a new session object.
477
   * Do user authentication through the session.
478
   */
479
  private void handleLoginAction(PrintWriter out, Hashtable params,
480
               HttpServletRequest request, HttpServletResponse response) {
481

    
482
    AuthSession sess = null;
483
    String un = ((String[])params.get("username"))[0];
484
    String pw = ((String[])params.get("password"))[0];
485
    String action = ((String[])params.get("action"))[0];
486
    String qformat = ((String[])params.get("qformat"))[0];
487

    
488
    try {
489
      sess = new AuthSession();
490
    } catch (Exception e) {
491
      System.out.println("error in MetacatServlet.handleLoginAction: " +
492
                          e.getMessage());
493
      out.println(e.getMessage());
494
      return;
495
    }
496
    boolean isValid = sess.authenticate(request, un, pw);
497
    // format and transform the output
498
    if (qformat.equals("xml")) {
499
      response.setContentType("text/xml");
500
      out.println(sess.getMessage());
501
    } else {
502

    
503
      try {
504

    
505
        DBTransform trans = new DBTransform();
506
        response.setContentType("text/html");
507
        trans.transformXMLDocument(sess.getMessage(), "-//NCEAS//login//EN",
508
                                   "-//W3C//HTML//EN", qformat, out, null);
509

    
510
      } catch(Exception e) {
511

    
512
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLoginAction: "
513
                                +e.getMessage(), 30);
514
      }
515

    
516
    // any output is returned
517
    }
518
  }
519

    
520
  /**
521
   * Handle the logout request. Close the connection.
522
   */
523
  private void handleLogoutAction(PrintWriter out, Hashtable params,
524
               HttpServletRequest request, HttpServletResponse response) {
525

    
526
    String qformat = ((String[])params.get("qformat"))[0];
527

    
528
    // close the connection
529
    HttpSession sess = request.getSession(false);
530
    if (sess != null) { sess.invalidate();  }
531

    
532
    // produce output
533
    StringBuffer output = new StringBuffer();
534
    output.append("<?xml version=\"1.0\"?>");
535
    output.append("<logout>");
536
    output.append("User logged out");
537
    output.append("</logout>");
538

    
539
    //format and transform the output
540
    if (qformat.equals("xml")) {
541
      response.setContentType("text/xml");
542
      out.println(output.toString());
543
    } else {
544

    
545
      try {
546

    
547
        DBTransform trans = new DBTransform();
548
        response.setContentType("text/html");
549
        trans.transformXMLDocument(output.toString(), "-//NCEAS//login//EN",
550
                                   "-//W3C//HTML//EN", qformat, out, null);
551

    
552
      } catch(Exception e) {
553

    
554
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLogoutAction"
555
                                  +e.getMessage(), 30);
556
      }
557
    }
558
  }
559
  // END OF LOGIN & LOGOUT SECTION
560

    
561
  // SQUERY & QUERY SECTION
562
  /**
563
   * Retreive the squery xml, execute it and display it
564
   *
565
   * @param out the output stream to the client
566
   * @param params the Hashtable of parameters that should be included
567
   * in the squery.
568
   * @param response the response object linked to the client
569
   * @param conn the database connection
570
   */
571
  protected void handleSQuery(PrintWriter out, Hashtable params,
572
                 HttpServletResponse response, String user, String[] groups,
573
                 String sessionid)
574
  {
575
    String xmlquery = ((String[])params.get("query"))[0];
576
    String qformat = ((String[])params.get("qformat"))[0];
577
    String resultdoc = null;
578
    MetaCatUtil.debugMessage("xmlquery: "+xmlquery, 30);
579
    double startTime = System.currentTimeMillis()/1000;
580
    Hashtable doclist = runQuery(xmlquery, user, groups);
581
    double docListTime = System.currentTimeMillis()/1000;
582
    MetaCatUtil.debugMessage("Time for getting doc list: "
583
                                            +(docListTime-startTime), 30);
584

    
585
    resultdoc = createResultDocument(doclist, transformQuery(xmlquery));
586
    double toStringTime = System.currentTimeMillis()/1000;
587
    MetaCatUtil.debugMessage("Time to create xml string: "
588
                              +(toStringTime-docListTime), 30);
589
    //format and transform the results
590
    double outPutTime = 0;
591
    if(qformat.equals("xml")) {
592
      response.setContentType("text/xml");
593
      out.println(resultdoc);
594
      outPutTime = System.currentTimeMillis()/1000;
595
      MetaCatUtil.debugMessage("Output time: "+(outPutTime-toStringTime), 30);
596
    } else {
597
      transformResultset(resultdoc, response, out, qformat, sessionid);
598
      outPutTime = System.currentTimeMillis()/1000;
599
      MetaCatUtil.debugMessage("Output time: "+(outPutTime-toStringTime), 30);
600
    }
601
  }
602

    
603
   /**
604
    * Create the xml query, execute it and display the results.
605
    *
606
    * @param out the output stream to the client
607
    * @param params the Hashtable of parameters that should be included
608
    * in the squery.
609
    * @param response the response object linked to the client
610
    */
611
  protected void handleQuery(PrintWriter out, Hashtable params,
612
                 HttpServletResponse response, String user, String[] groups,
613
                 String sessionid)
614
  {
615
    //create the query and run it
616
    String xmlquery = DBQuery.createSQuery(params);
617
    Hashtable doclist = runQuery(xmlquery, user, groups);
618
    String qformat = ((String[])params.get("qformat"))[0];
619
    String resultdoc = null;
620

    
621
    resultdoc = createResultDocument(doclist, transformQuery(params));
622

    
623
    //format and transform the results
624
    if(qformat.equals("xml")) {
625
      response.setContentType("text/xml");
626
      out.println(resultdoc);
627
    } else {
628
      transformResultset(resultdoc, response, out, qformat, sessionid);
629
    }
630
  }
631

    
632
  /**
633
   * Removes the <?xml version="x"?> tag from the beginning of xmlquery
634
   * so it can properly be placed in the <query> tag of the resultset.
635
   * This method is overwritable so that other applications can customize
636
   * the structure of what is in the <query> tag.
637
   *
638
   * @param xmlquery is the query to remove the <?xml version="x"?> tag from.
639
   */
640
  protected String transformQuery(Hashtable params)
641
  {
642
    //DBQuery.createSQuery is a re-calling of a previously called
643
    //function but it is necessary
644
    //so that overriding methods have access to the params hashtable
645
    String xmlquery = DBQuery.createSQuery(params);
646
    //the <?xml version="1.0"?> tag is the first 22 characters of the
647
    xmlquery = xmlquery.trim();
648
    int index = xmlquery.indexOf("?>");
649
    if ( index != -1 )
650
    {
651
      //have <?xml version="1.0"?>
652
      return xmlquery.substring(index + 2, xmlquery.length());
653
    }
654
    else
655
    {
656
      // don't have <?xml version="1.0"?>
657
      return xmlquery;
658
    }
659
  }
660

    
661
  /**
662
   * removes the <?xml version="1.0"?> tag from the beginning.  This takes a
663
   * string as a param instead of a hashtable.
664
   *
665
   * @param xmlquery a string representing a query.
666
   */
667
  protected String transformQuery(String xmlquery)
668
  {
669
    xmlquery = xmlquery.trim();
670
    int index = xmlquery.indexOf("?>");
671
    if (index != -1)
672
    {
673
      return xmlquery.substring(index + 2, xmlquery.length());
674
    }
675
    else
676
    {
677
      return xmlquery;
678
    }
679
  }
680

    
681
  /**
682
   * Run the query and return a hashtable of results.
683
   *
684
   * @param xmlquery the query to run
685
   */
686
  private Hashtable runQuery(String xmlquery, String user, String[] groups)
687
  {
688
    Hashtable doclist=null;
689

    
690
    try
691
    {
692

    
693
      DBQuery queryobj = new DBQuery(saxparser);
694
      doclist = queryobj.findDocuments(new StringReader(xmlquery),user,groups);
695

    
696
      return doclist;
697
    }
698
    catch (Exception e)
699
    {
700

    
701
      MetaCatUtil.debugMessage("Error in MetacatServlet.runQuery: "
702
                                                      + e.getMessage(), 30);
703
      doclist = null;
704
      return doclist;
705
    }
706
  }
707

    
708
  /**
709
   * Transorms an xml resultset document to html and sends it to the browser
710
   *
711
   * @param resultdoc the string representation of the document that needs
712
   * to be transformed.
713
   * @param response the HttpServletResponse object bound to the client.
714
   * @param out the output stream to the client
715
   * @param qformat the name of the style-set to use for transformations
716
   */
717
  protected void transformResultset(String resultdoc,
718
                                    HttpServletResponse response,
719
                                    PrintWriter out, String qformat,
720
                                    String sessionid)
721
  {
722

    
723
    try {
724

    
725
      DBTransform trans = new DBTransform();
726
      response.setContentType("text/html");
727
      trans.transformXMLDocument(resultdoc, "-//NCEAS//resultset//EN",
728
                                 "-//W3C//HTML//EN", qformat, out, null,
729
                                 sessionid);
730

    
731
    }
732
    catch(Exception e)
733
    {
734

    
735
      MetaCatUtil.debugMessage("Error in MetaCatServlet.transformResultset:"
736
                                +e.getMessage(), 30);
737
    }
738
  }
739

    
740
  /**
741
   * Transforms a hashtable of documents to an xml or html result.
742
   *
743
   * @param doclist- the hashtable to transform
744
   * @param xmlquery- the query that returned the doclist result
745
   */
746
  protected String createResultDocument(Hashtable doclist, String xmlquery)
747
  {
748
    // Create a buffer to hold the xml result
749
    StringBuffer resultset = new StringBuffer();
750

    
751
    // Print the resulting root nodes
752
    String docid = null;
753
    String document = null;
754
    resultset.append("<?xml version=\"1.0\"?>\n");
755
    resultset.append("<resultset>\n");
756

    
757
    resultset.append("  <query>" + xmlquery + "</query>");
758

    
759
    if(doclist != null)
760
    {
761
      Enumeration doclistkeys = doclist.keys();
762
      while (doclistkeys.hasMoreElements())
763
      {
764
        docid = (String)doclistkeys.nextElement();
765
        document = (String)doclist.get(docid);
766
        resultset.append("  <document>" + document + "</document>");
767
      }
768
    }
769

    
770
    resultset.append("</resultset>");
771
    return resultset.toString();
772
  }
773
  // END OF SQUERY & QUERY SECTION
774

    
775
 //Exoport section
776
 /**
777
   * Handle the "export" request of data package from Metacat in zip format
778
   * @param params the Hashtable of HTTP request parameters
779
   * @param response the HTTP response object linked to the client
780
   * @param user the username sent the request
781
   * @param groups the user's groupnames
782
   */
783
  private void handleExportAction(Hashtable params,
784
    HttpServletResponse response, String user, String[] groups, String passWord)
785
  {
786
    // Output stream
787
    ServletOutputStream out = null;
788
    // Zip output stream
789
    ZipOutputStream zOut = null;
790
    DocumentImpl docImpls=null;
791
    DBQuery queryObj=null;
792

    
793
    String[] docs = new String[10];
794
    String docId = "";
795

    
796
    try
797
    {
798
      // read the params
799
      if (params.containsKey("docid"))
800
      {
801
        docs = (String[])params.get("docid");
802
      }//if
803
      // Create a DBuery to handle export
804
      queryObj = new DBQuery(saxparser);
805
      // Get the docid
806
      docId=docs[0];
807
      // Make sure the client specify docid
808
      if (docId == null || docId.equals(""))
809
      {
810
        response.setContentType("text/xml"); //MIME type
811
        // Get a printwriter
812
        PrintWriter pw = response.getWriter();
813
        // Send back message
814
        pw.println("<?xml version=\"1.0\"?>");
815
        pw.println("<error>");
816
        pw.println("You didn't specify requested docid");
817
        pw.println("</error>");
818
        // Close printwriter
819
        pw.close();
820
        return;
821
      }//if
822
      // Get output stream
823
      out = response.getOutputStream();
824
      response.setContentType("application/zip"); //MIME type
825
      zOut = new ZipOutputStream(out);
826
      zOut =queryObj.getZippedPackage(docId, out, user, groups, passWord);
827
      zOut.finish(); //terminate the zip file
828
      zOut.close();  //close the zip stream
829

    
830
    }//try
831
    catch (Exception e)
832
    {
833
      try
834
      {
835
        response.setContentType("text/xml"); //MIME type
836
        // Send error message back
837
        if (out != null)
838
        {
839
            PrintWriter pw = new PrintWriter(out);
840
            pw.println("<?xml version=\"1.0\"?>");
841
            pw.println("<error>");
842
            pw.println(e.getMessage());
843
            pw.println("</error>");
844
            // Close printwriter
845
            pw.close();
846
            // Close output stream
847
            out.close();
848
        }//if
849
        // Close zip output stream
850
        if ( zOut != null )
851
        {
852
          zOut.close();
853
        }//if
854
      }//try
855
      catch (IOException ioe)
856
      {
857
        MetaCatUtil.debugMessage("Problem with the servlet output " +
858
                           "in MetacatServlet.handleExportAction: " +
859
                           ioe.getMessage(), 30);
860
      }//catch
861

    
862
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleExportAction: " +
863
                         e.getMessage(), 30);
864
      e.printStackTrace(System.out);
865

    
866
    }//catch
867

    
868
  }//handleExportAction
869

    
870

    
871
   //read inline data section
872
 /**
873
   * In eml2 document, the xml can have inline data and data was stripped off
874
   * and store in file system. This action can be used to read inline data only
875
   * @param params the Hashtable of HTTP request parameters
876
   * @param response the HTTP response object linked to the client
877
   * @param user the username sent the request
878
   * @param groups the user's groupnames
879
   */
880
  private void handleReadInlineDataAction(Hashtable params,
881
                                          HttpServletResponse response,
882
                                          String user, String passWord,
883
                                          String[] groups)
884
  {
885
    String[] docs = new String[10];
886
    String inlineDataId = null;
887
    String docId = "";
888
    ServletOutputStream out = null;
889

    
890
    try
891
    {
892
      // read the params
893
      if (params.containsKey("inlinedataid"))
894
      {
895
        docs = (String[])params.get("inlinedataid");
896
      }//if
897
      // Get the docid
898
      inlineDataId=docs[0];
899
      // Make sure the client specify docid
900
      if (inlineDataId == null || inlineDataId.equals(""))
901
      {
902
        throw new Exception("You didn't specify requested inlinedataid");
903
      }//if
904

    
905
      // check for permission
906
      docId = MetaCatUtil.getDocIdWithoutRevFromInlineDataID(inlineDataId);
907
      PermissionController controller = new PermissionController(docId);
908
      // check top level read permission
909
      if (!controller.hasPermission(user, groups,
910
                                    AccessControlInterface.READSTRING))
911
      {
912
          throw new Exception("User "+ user + " doesn't have permission "+
913
                              " to read document " + docId);
914
      }//if
915
      // if the document has subtree control, we need to check subtree control
916
      else if(controller.hasSubTreeAccessControl())
917
      {
918
        // get node id for inlinedata
919
        long nodeId=getInlineDataNodeId(inlineDataId, docId);
920
        if (!controller.hasPermissionForSubTreeNode(user, groups,
921
                                     AccessControlInterface.READSTRING, nodeId))
922
        {
923
           throw new Exception("User "+ user + " doesn't have permission "+
924
                              " to read inlinedata " + inlineDataId);
925
        }//if
926

    
927
      }//else
928

    
929
      // Get output stream
930
      out = response.getOutputStream();
931
      // read the inline data from the file
932
      String inlinePath = MetaCatUtil.getOption("inlinedatafilepath");
933
      File lineData = new File(inlinePath, inlineDataId);
934
      FileInputStream input = new FileInputStream(lineData);
935
      byte [] buffer = new byte[4*1024];
936
      int bytes = input.read(buffer);
937
      while (bytes != -1)
938
      {
939
        out.write(buffer, 0, bytes);
940
        bytes = input.read(buffer);
941
      }
942
      out.close();
943

    
944
    }//try
945
    catch (Exception e)
946
    {
947
      try
948
      {
949
        PrintWriter pw = null;
950
        // Send error message back
951
        if (out != null)
952
        {
953
            pw = new PrintWriter(out);
954
        }//if
955
        else
956
        {
957
          pw = response.getWriter();
958
        }
959
         pw.println("<?xml version=\"1.0\"?>");
960
         pw.println("<error>");
961
         pw.println(e.getMessage());
962
         pw.println("</error>");
963
         // Close printwriter
964
         pw.close();
965
         // Close output stream if out is not null
966
         if (out != null)
967
         {
968
           out.close();
969
         }
970
     }//try
971
     catch (IOException ioe)
972
     {
973
        MetaCatUtil.debugMessage("Problem with the servlet output " +
974
                           "in MetacatServlet.handleExportAction: " +
975
                           ioe.getMessage(), 30);
976
     }//catch
977

    
978
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleReadInlineDataAction: "
979
                                + e.getMessage(), 30);
980

    
981
    }//catch
982

    
983
  }//handleReadInlineDataAction
984

    
985
  /*
986
   * Get the nodeid from xml_nodes for the inlinedataid
987
   */
988
  private long getInlineDataNodeId(String inLineDataId, String docId)
989
                                   throws SQLException
990
  {
991
    long nodeId = 0;
992
    String INLINE = "inline";
993
    boolean hasRow;
994
    PreparedStatement pStmt = null;
995
    DBConnection conn = null;
996
    int serialNumber = -1;
997
    String sql ="SELECT nodeid FROM xml_nodes WHERE docid=? AND nodedata=? " +
998
                "AND nodetype='TEXT' AND parentnodeid IN " +
999
                "(SELECT nodeid FROM xml_nodes WHERE docid=? AND " +
1000
                "nodetype='ELEMENT' AND nodename='" + INLINE + "')";
1001

    
1002
    try
1003
    {
1004
      //check out DBConnection
1005
      conn=DBConnectionPool.getDBConnection("AccessControlList.isAllowFirst");
1006
      serialNumber=conn.getCheckOutSerialNumber();
1007

    
1008
      pStmt = conn.prepareStatement(sql);
1009
      //bind value
1010
      pStmt.setString(1, docId);//docid
1011
      pStmt.setString(2, inLineDataId);//inlinedataid
1012
      pStmt.setString(3, docId);
1013
      // excute query
1014
      pStmt.execute();
1015
      ResultSet rs = pStmt.getResultSet();
1016
      hasRow=rs.next();
1017
      // get result
1018
      if (hasRow)
1019
      {
1020
        nodeId = rs.getLong(1);
1021
      }//if
1022

    
1023
    }//try
1024
    catch (SQLException e)
1025
    {
1026
      throw e;
1027
    }
1028
    finally
1029
    {
1030
      try
1031
      {
1032
        pStmt.close();
1033
      }
1034
      finally
1035
      {
1036
        DBConnectionPool.returnDBConnection(conn, serialNumber);
1037
      }
1038
    }
1039
    MetaCatUtil.debugMessage("The nodeid for inlinedataid " + inLineDataId +
1040
                             " is: "+nodeId, 35);
1041
    return nodeId;
1042
  }
1043

    
1044

    
1045

    
1046
  // READ SECTION
1047
  /**
1048
   * Handle the "read" request of metadata/data files from Metacat
1049
   * or any files from Internet;
1050
   * transformed metadata XML document into HTML presentation if requested;
1051
   * zip files when more than one were requested.
1052
   *
1053
   * @param params the Hashtable of HTTP request parameters
1054
   * @param response the HTTP response object linked to the client
1055
   * @param user the username sent the request
1056
   * @param groups the user's groupnames
1057
   */
1058
  private void handleReadAction(Hashtable params, HttpServletResponse response,
1059
                                String user, String passWord, String[] groups)
1060
  {
1061
    ServletOutputStream out = null;
1062
    ZipOutputStream zout = null;
1063
    PrintWriter pw = null;
1064
    boolean zip = false;
1065
    boolean withInlineData = true;
1066

    
1067
    try {
1068
      String[] docs = new String[0];
1069
      String docid = "";
1070
      String qformat = "";
1071
      String abstrpath = null;
1072

    
1073
      // read the params
1074
      if (params.containsKey("docid")) {
1075
        docs = (String[])params.get("docid");
1076
      }
1077
      if (params.containsKey("qformat")) {
1078
        qformat = ((String[])params.get("qformat"))[0];
1079
      }
1080
      // the param for only metadata (eml)
1081
      if (params.containsKey("inlinedata"))
1082
      {
1083

    
1084
        String inlineData = ((String[])params.get("inlinedata"))[0];
1085
        if (inlineData.equalsIgnoreCase("false"))
1086
        {
1087
          withInlineData = false;
1088
        }
1089
      }
1090
      if (params.containsKey("abstractpath")) {
1091
        abstrpath = ((String[])params.get("abstractpath"))[0];
1092
        if ( !abstrpath.equals("") && (abstrpath != null) ) {
1093
          viewAbstract(response, abstrpath, docs[0]);
1094
          return;
1095
        }
1096
      }
1097
      if ( (docs.length > 1) || qformat.equals("zip") ) {
1098
        zip = true;
1099
        out = response.getOutputStream();
1100
        response.setContentType("application/zip"); //MIME type
1101
        zout = new ZipOutputStream(out);
1102
      }
1103
      // go through the list of docs to read
1104
      for (int i=0; i < docs.length; i++ ) {
1105
        try {
1106

    
1107
          URL murl = new URL(docs[i]);
1108
          Hashtable murlQueryStr = util.parseQuery(murl.getQuery());
1109
          // case docid="http://.../?docid=aaa"
1110
          // or docid="metacat://.../?docid=bbb"
1111
          if (murlQueryStr.containsKey("docid")) {
1112
            // get only docid, eliminate the rest
1113
            docid = (String)murlQueryStr.get("docid");
1114
            if ( zip ) {
1115
              addDocToZip(docid, zout, user, groups);
1116
            } else {
1117
              readFromMetacat(response, docid, qformat, abstrpath,
1118
                              user, groups, zip, zout, withInlineData, params);
1119
            }
1120

    
1121
          // case docid="http://.../filename"
1122
          } else {
1123
            docid = docs[i];
1124
            if ( zip ) {
1125
              addDocToZip(docid, zout, user, groups);
1126
            } else {
1127
              readFromURLConnection(response, docid);
1128
            }
1129
          }
1130

    
1131
        // case docid="ccc"
1132
        } catch (MalformedURLException mue) {
1133
          docid = docs[i];
1134
          if ( zip ) {
1135
            addDocToZip(docid, zout, user, groups);
1136
          } else {
1137
            readFromMetacat(response, docid, qformat, abstrpath,
1138
                            user, groups, zip, zout, withInlineData, params);
1139
          }
1140
        }
1141

    
1142
      } /* end for */
1143

    
1144
      if ( zip ) {
1145
        zout.finish(); //terminate the zip file
1146
        zout.close();  //close the zip stream
1147
      }
1148

    
1149

    
1150
    }
1151
    // To handle doc not found exception
1152
    catch (McdbDocNotFoundException notFoundE)
1153
    {
1154
      // the docid which didn't be found
1155
      String notFoundDocId = notFoundE.getUnfoundDocId();
1156
      String notFoundRevision = notFoundE.getUnfoundRevision();
1157
      MetaCatUtil.debugMessage("Missed id: "+ notFoundDocId, 30);
1158
      MetaCatUtil.debugMessage("Missed rev: "+ notFoundRevision, 30);
1159
      try
1160
      {
1161
        // read docid from remote server
1162
        readFromRemoteMetaCat(response, notFoundDocId, notFoundRevision,
1163
                                              user, passWord, out, zip, zout);
1164
        // Close zout outputstream
1165
        if ( zout != null)
1166
        {
1167
          zout.close();
1168
        }
1169
        // close output stream
1170
        if (out != null)
1171
        {
1172
          out.close();
1173
        }
1174

    
1175
      }//try
1176
      catch ( Exception exc)
1177
      {
1178
        MetaCatUtil.debugMessage("Erorr in MetacatServlet.hanldReadAction: "+
1179
                                      exc.getMessage(), 30);
1180
        try
1181
        {
1182
          if (out != null)
1183
          {
1184
            response.setContentType("text/xml");
1185
            // Send back error message by printWriter
1186
            pw = new PrintWriter(out);
1187
            pw.println("<?xml version=\"1.0\"?>");
1188
            pw.println("<error>");
1189
            pw.println(notFoundE.getMessage());
1190
            pw.println("</error>");
1191
            pw.close();
1192
            out.close();
1193

    
1194
          }
1195
          else
1196
          {
1197
           response.setContentType("text/xml"); //MIME type
1198
           // Send back error message if out = null
1199
           if (pw == null)
1200
           {
1201
             // If pw is null, open the respnose
1202
            pw = response.getWriter();
1203
           }
1204
           pw.println("<?xml version=\"1.0\"?>");
1205
           pw.println("<error>");
1206
           pw.println(notFoundE.getMessage());
1207
           pw.println("</error>");
1208
           pw.close();
1209
        }
1210
        // close zout
1211
        if ( zout != null )
1212
        {
1213
          zout.close();
1214
        }
1215
        }//try
1216
        catch (IOException ie)
1217
        {
1218
          MetaCatUtil.debugMessage("Problem with the servlet output " +
1219
                           "in MetacatServlet.handleReadAction: " +
1220
                           ie.getMessage(), 30);
1221
        }//cathch
1222
      }//catch
1223
    }// catch McdbDocNotFoundException
1224
    catch (Exception e)
1225
    {
1226
      try {
1227

    
1228
        if (out != null) {
1229
            response.setContentType("text/xml"); //MIME type
1230
            pw = new PrintWriter(out);
1231
            pw.println("<?xml version=\"1.0\"?>");
1232
            pw.println("<error>");
1233
            pw.println(e.getMessage());
1234
            pw.println("</error>");
1235
            pw.close();
1236
            out.close();
1237
        }
1238
        else
1239
        {
1240
           response.setContentType("text/xml"); //MIME type
1241
           // Send back error message if out = null
1242
           if ( pw == null)
1243
           {
1244
            pw = response.getWriter();
1245
           }
1246
           pw.println("<?xml version=\"1.0\"?>");
1247
           pw.println("<error>");
1248
           pw.println(e.getMessage());
1249
           pw.println("</error>");
1250
           pw.close();
1251

    
1252
        }
1253
        // Close zip output stream
1254
        if ( zout != null ) { zout.close(); }
1255

    
1256
      } catch (IOException ioe) {
1257
        MetaCatUtil.debugMessage("Problem with the servlet output " +
1258
                           "in MetacatServlet.handleReadAction: " +
1259
                           ioe.getMessage(), 30);
1260
        ioe.printStackTrace(System.out);
1261

    
1262
      }
1263

    
1264
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleReadAction: " +
1265
                               e.getMessage(), 30);
1266
      //e.printStackTrace(System.out);
1267
    }
1268

    
1269
  }
1270

    
1271
  // read metadata or data from Metacat
1272
  private void readFromMetacat(HttpServletResponse response, String docid,
1273
                               String qformat, String abstrpath, String user,
1274
                               String[] groups, boolean zip,
1275
                               ZipOutputStream zout, boolean withInlineData,
1276
                               Hashtable params)
1277
               throws ClassNotFoundException, IOException, SQLException,
1278
                      McdbException, Exception
1279
  {
1280

    
1281
    try {
1282

    
1283

    
1284
      DocumentImpl doc = new DocumentImpl(docid);
1285

    
1286
      //check the permission for read
1287
      if (!doc.hasReadPermission(user, groups, docid))
1288
      {
1289
        Exception e = new Exception("User " + user + " does not have permission"
1290
                       +" to read the document with the docid " + docid);
1291

    
1292
        throw e;
1293
      }
1294

    
1295
      if ( doc.getRootNodeID() == 0 ) {
1296
        // this is data file
1297
        String filepath = util.getOption("datafilepath");
1298
        if(!filepath.endsWith("/")) {
1299
          filepath += "/";
1300
        }
1301
        String filename = filepath + docid;
1302
        FileInputStream fin = null;
1303
        fin = new FileInputStream(filename);
1304

    
1305
        //MIME type
1306
        String contentType = getServletContext().getMimeType(filename);
1307
        if (contentType == null)
1308
        {
1309
          ContentTypeProvider provider = new ContentTypeProvider(docid);
1310
          contentType = provider.getContentType();
1311
          MetaCatUtil.debugMessage("Final contenttype is: "+ contentType, 30);
1312
        }
1313

    
1314
        response.setContentType(contentType);
1315
        // if we decide to use "application/octet-stream" for all data returns
1316
        // response.setContentType("application/octet-stream");
1317

    
1318
        try {
1319

    
1320
          ServletOutputStream out = response.getOutputStream();
1321
          byte[] buf = new byte[4 * 1024]; // 4K buffer
1322
          int b = fin.read(buf);
1323
          while (b != -1) {
1324
            out.write(buf, 0, b);
1325
            b = fin.read(buf);
1326
          }
1327
        } finally {
1328
          if (fin != null) fin.close();
1329
        }
1330

    
1331
      } else {
1332
        // this is metadata doc
1333
        if ( qformat.equals("xml") ) {
1334

    
1335
          // set content type first
1336
          response.setContentType("text/xml");   //MIME type
1337
          PrintWriter out = response.getWriter();
1338
          doc.toXml(out, user, groups, withInlineData);
1339
        } else {
1340
          response.setContentType("text/html");  //MIME type
1341
          PrintWriter out = response.getWriter();
1342

    
1343
          // Look up the document type
1344
          String doctype = doc.getDoctype();
1345
          // Transform the document to the new doctype
1346
          DBTransform dbt = new DBTransform();
1347
          dbt.transformXMLDocument(doc.toString(user, groups, withInlineData),
1348
                                   doctype,"-//W3C//HTML//EN",
1349
                                   qformat, out, params);
1350
        }
1351

    
1352
      }
1353
    }
1354
    catch (Exception except)
1355
    {
1356
      throw except;
1357

    
1358
    }
1359

    
1360
  }
1361

    
1362
  // read data from URLConnection
1363
  private void readFromURLConnection(HttpServletResponse response, String docid)
1364
               throws IOException, MalformedURLException
1365
  {
1366
    ServletOutputStream out = response.getOutputStream();
1367
    String contentType = getServletContext().getMimeType(docid); //MIME type
1368
    if (contentType == null) {
1369
      if (docid.endsWith(".xml")) {
1370
        contentType="text/xml";
1371
      } else if (docid.endsWith(".css")) {
1372
        contentType="text/css";
1373
      } else if (docid.endsWith(".dtd")) {
1374
        contentType="text/plain";
1375
      } else if (docid.endsWith(".xsd")) {
1376
        contentType="text/xml";
1377
      } else if (docid.endsWith("/")) {
1378
        contentType="text/html";
1379
      } else {
1380
        File f = new File(docid);
1381
        if ( f.isDirectory() ) {
1382
          contentType="text/html";
1383
        } else {
1384
          contentType="application/octet-stream";
1385
        }
1386
      }
1387
    }
1388
    response.setContentType(contentType);
1389
    // if we decide to use "application/octet-stream" for all data returns
1390
    // response.setContentType("application/octet-stream");
1391

    
1392
    // this is http url
1393
    URL url = new URL(docid);
1394
    BufferedInputStream bis = null;
1395
    try {
1396
      bis = new BufferedInputStream(url.openStream());
1397
      byte[] buf = new byte[4 * 1024]; // 4K buffer
1398
      int b = bis.read(buf);
1399
      while (b != -1) {
1400
        out.write(buf, 0, b);
1401
        b = bis.read(buf);
1402
      }
1403
    } finally {
1404
      if (bis != null) bis.close();
1405
    }
1406

    
1407
  }
1408

    
1409
  // read file/doc and write to ZipOutputStream
1410
  private void addDocToZip(String docid, ZipOutputStream zout,
1411
                              String user, String[] groups)
1412
               throws ClassNotFoundException, IOException, SQLException,
1413
                      McdbException, Exception
1414
  {
1415
    byte[] bytestring = null;
1416
    ZipEntry zentry = null;
1417

    
1418
    try {
1419
      URL url = new URL(docid);
1420

    
1421
      // this http url; read from URLConnection; add to zip
1422
      zentry = new ZipEntry(docid);
1423
      zout.putNextEntry(zentry);
1424
      BufferedInputStream bis = null;
1425
      try {
1426
        bis = new BufferedInputStream(url.openStream());
1427
        byte[] buf = new byte[4 * 1024]; // 4K buffer
1428
        int b = bis.read(buf);
1429
        while(b != -1) {
1430
          zout.write(buf, 0, b);
1431
          b = bis.read(buf);
1432
        }
1433
      } finally {
1434
        if (bis != null) bis.close();
1435
      }
1436
      zout.closeEntry();
1437

    
1438
    } catch (MalformedURLException mue) {
1439

    
1440
      // this is metacat doc (data file or metadata doc)
1441

    
1442
      try {
1443

    
1444
        DocumentImpl doc = new DocumentImpl(docid);
1445

    
1446
        //check the permission for read
1447
        if (!doc.hasReadPermission(user, groups, docid))
1448
        {
1449
          Exception e = new Exception("User " + user + " does not have "
1450
                    +"permission to read the document with the docid " + docid);
1451

    
1452
          throw e;
1453
        }
1454

    
1455
        if ( doc.getRootNodeID() == 0 ) {
1456
          // this is data file; add file to zip
1457
          String filepath = util.getOption("datafilepath");
1458
          if(!filepath.endsWith("/")) {
1459
            filepath += "/";
1460
          }
1461
          String filename = filepath + docid;
1462
          FileInputStream fin = null;
1463
          fin = new FileInputStream(filename);
1464
          try {
1465

    
1466
            zentry = new ZipEntry(docid);
1467
            zout.putNextEntry(zentry);
1468
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1469
            int b = fin.read(buf);
1470
            while (b != -1) {
1471
              zout.write(buf, 0, b);
1472
              b = fin.read(buf);
1473
            }
1474
          } finally {
1475
            if (fin != null) fin.close();
1476
          }
1477
          zout.closeEntry();
1478

    
1479
        } else {
1480
          // this is metadata doc; add doc to zip
1481
          bytestring = doc.toString().getBytes();
1482
          zentry = new ZipEntry(docid + ".xml");
1483
          zentry.setSize(bytestring.length);
1484
          zout.putNextEntry(zentry);
1485
          zout.write(bytestring, 0, bytestring.length);
1486
          zout.closeEntry();
1487
        }
1488
      } catch (Exception except) {
1489
        throw except;
1490

    
1491
      }
1492

    
1493
    }
1494

    
1495
  }
1496

    
1497
  // view abstract within document
1498
  private void viewAbstract(HttpServletResponse response,
1499
                            String abstractpath, String docid)
1500
               throws ClassNotFoundException, IOException, SQLException,
1501
                      McdbException, Exception
1502
  {
1503

    
1504
    PrintWriter out =null;
1505
    try {
1506

    
1507
      response.setContentType("text/html");  //MIME type
1508
      out = response.getWriter();
1509
      Object[] abstracts = DBQuery.getNodeContent(abstractpath, docid);
1510
      out.println("<html><head><title>Abstract</title></head>");
1511
      out.println("<body bgcolor=\"white\"><h1>Abstract</h1>");
1512
      for (int i=0; i<abstracts.length; i++) {
1513
        out.println("<p>" + (String)abstracts[i] + "</p>");
1514
      }
1515
      out.println("</body></html>");
1516

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

    
1523

    
1524
    }
1525
  }
1526
  /**
1527
   * If metacat couldn't find a data file or document locally, it will read this
1528
   * docid from its home server. This is for the replication feature
1529
   */
1530
  private void readFromRemoteMetaCat(HttpServletResponse response, String docid,
1531
                     String rev, String user, String password,
1532
                     ServletOutputStream out, boolean zip, ZipOutputStream zout)
1533
                        throws Exception
1534
 {
1535
   // Create a object of RemoteDocument, "" is for zipEntryPath
1536
   RemoteDocument remoteDoc =
1537
                        new RemoteDocument (docid, rev,user, password, "");
1538
   String docType = remoteDoc.getDocType();
1539
   // Only read data file
1540
   if (docType.equals("BIN"))
1541
   {
1542
    // If it is zip format
1543
    if (zip)
1544
    {
1545
      remoteDoc.readDocumentFromRemoteServerByZip(zout);
1546
    }//if
1547
    else
1548
    {
1549
      if (out == null)
1550
      {
1551
        out = response.getOutputStream();
1552
      }//if
1553
      response.setContentType("application/octet-stream");
1554
      remoteDoc.readDocumentFromRemoteServer(out);
1555
    }//else (not zip)
1556
   }//if doctype=bin
1557
   else
1558
   {
1559
     throw new Exception("Docid: "+docid+"."+rev+" couldn't find");
1560
   }//else
1561
 }//readFromRemoteMetaCat
1562

    
1563
  // END OF READ SECTION
1564

    
1565

    
1566

    
1567
  // INSERT/UPDATE SECTION
1568
  /**
1569
   * Handle the database putdocument request and write an XML document
1570
   * to the database connection
1571
   */
1572
  private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params,
1573
               String user, String[] groups) {
1574

    
1575
    DBConnection dbConn = null;
1576
    int serialNumber = -1;
1577

    
1578
    try {
1579
      // Get the document indicated
1580
      String[] doctext = (String[])params.get("doctext");
1581

    
1582
      String pub = null;
1583
      if (params.containsKey("public")) {
1584
        pub = ((String[])params.get("public"))[0];
1585
      }
1586

    
1587
      StringReader dtd = null;
1588
      if (params.containsKey("dtdtext")) {
1589
        String[] dtdtext = (String[])params.get("dtdtext");
1590
        try {
1591
          if ( !dtdtext[0].equals("") ) {
1592
            dtd = new StringReader(dtdtext[0]);
1593
          }
1594
        } catch (NullPointerException npe) {}
1595
      }
1596

    
1597
      StringReader xml = new StringReader(doctext[0]);
1598
      boolean validate = false;
1599
      DocumentImplWrapper documentWrapper = null;
1600
      try {
1601
        // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1602
        // in order to decide whether to use validation parser
1603
        validate = needDTDValidation(xml);
1604
        if (validate)
1605
        {
1606
          // set a dtd base validation parser
1607
          String rule = DocumentImpl.DTD;
1608
          documentWrapper = new DocumentImplWrapper(rule, validate);
1609
        }
1610
        else if (needSchemaValidation(xml))
1611
        {
1612
          // for eml2
1613
          if (needEml2Validation(xml))
1614
          {
1615
             // set eml2 base validation parser
1616
            String rule = DocumentImpl.EML2;
1617
            // using emlparser to check id validation
1618
            EMLParser parser = new EMLParser(doctext[0]);
1619
            documentWrapper = new DocumentImplWrapper(rule, true);
1620
          }
1621
          else
1622
          {
1623
            // set schema base validation parser
1624
            String rule = DocumentImpl.SCHEMA;
1625
            documentWrapper = new DocumentImplWrapper(rule, true);
1626
          }
1627
        }
1628
        else
1629
        {
1630
          documentWrapper = new DocumentImplWrapper("", false);
1631
        }
1632

    
1633
        String[] action = (String[])params.get("action");
1634
        String[] docid = (String[])params.get("docid");
1635
        String newdocid = null;
1636

    
1637
        String doAction = null;
1638
        if (action[0].equals("insert")) {
1639
          doAction = "INSERT";
1640
        } else if (action[0].equals("update")) {
1641
          doAction = "UPDATE";
1642
        }
1643

    
1644
        try
1645
        {
1646
          // get a connection from the pool
1647
          dbConn=DBConnectionPool.
1648
                  getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1649
          serialNumber=dbConn.getCheckOutSerialNumber();
1650

    
1651
           // write the document to the database
1652
          try
1653
          {
1654
            String accNumber = docid[0];
1655
            MetaCatUtil.debugMessage(""+ doAction + " " + accNumber +"...", 10);
1656
            if (accNumber.equals(""))
1657
            {
1658
              accNumber = null;
1659
            }//if
1660
            newdocid = documentWrapper.write(dbConn, xml, pub, dtd, doAction,
1661
                                          accNumber, user, groups);
1662

    
1663
          }//try
1664
          catch (NullPointerException npe)
1665
          {
1666
            newdocid = documentWrapper.write(dbConn, xml, pub, dtd, doAction,
1667
                                          null, user, groups);
1668
          }//catch
1669

    
1670
        }//try
1671
        finally
1672
        {
1673
          // Return db connection
1674
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1675
        }
1676

    
1677
        // set content type and other response header fields first
1678
        //response.setContentType("text/xml");
1679
        out.println("<?xml version=\"1.0\"?>");
1680
        out.println("<success>");
1681
        out.println("<docid>" + newdocid + "</docid>");
1682
        out.println("</success>");
1683

    
1684
      }
1685
      catch (NullPointerException npe)
1686
      {
1687
        //response.setContentType("text/xml");
1688
        out.println("<?xml version=\"1.0\"?>");
1689
        out.println("<error>");
1690
        out.println(npe.getMessage());
1691
        out.println("</error>");
1692
      }
1693
    }
1694
    catch (Exception e)
1695
    {
1696
      //response.setContentType("text/xml");
1697
      out.println("<?xml version=\"1.0\"?>");
1698
      out.println("<error>");
1699
      out.println(e.getMessage());
1700
      out.println("</error>");
1701
    }
1702
  }
1703

    
1704
  /**
1705
   * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1706
   * in order to decide whether to use validation parser
1707
   */
1708
  private static boolean needDTDValidation(StringReader xmlreader) throws 
1709
                                                             IOException 
1710
  {
1711

    
1712
    
1713
    StringBuffer cbuff = new StringBuffer();
1714
    java.util.Stack st = new java.util.Stack();
1715
    boolean validate = false;
1716
    int c;
1717
    int inx;
1718

    
1719
    // read from the stream until find the keywords
1720
    while ( (st.empty() || st.size()<4) && ((c = xmlreader.read()) != -1) ) {
1721
      cbuff.append((char)c);
1722

    
1723
      // "<!DOCTYPE" keyword is found; put it in the stack
1724
      if ( (inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1 ) {
1725
        cbuff = new StringBuffer();
1726
        st.push("<!DOCTYPE");
1727
      }
1728
      // "PUBLIC" keyword is found; put it in the stack
1729
      if ( (inx = cbuff.toString().indexOf("PUBLIC")) != -1 ) {
1730
        cbuff = new StringBuffer();
1731
        st.push("PUBLIC");
1732
      }
1733
      // "SYSTEM" keyword is found; put it in the stack
1734
      if ( (inx = cbuff.toString().indexOf("SYSTEM")) != -1 ) {
1735
        cbuff = new StringBuffer();
1736
        st.push("SYSTEM");
1737
      }
1738
      // ">" character is found; put it in the stack
1739
      // ">" is found twice: fisrt from <?xml ...?>
1740
      // and second from <!DOCTYPE ... >
1741
      if ( (inx = cbuff.toString().indexOf(">")) != -1 ) {
1742
        cbuff = new StringBuffer();
1743
        st.push(">");
1744
      }
1745
    }
1746

    
1747
    // close the stream
1748
    xmlreader.reset();
1749

    
1750
    // check the stack whether it contains the keywords:
1751
    // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1752
    if ( st.size() == 4 ) {
1753
      if ( ((String)st.pop()).equals(">") &&
1754
           ( ((String)st.peek()).equals("PUBLIC") |
1755
             ((String)st.pop()).equals("SYSTEM") ) &&
1756
           ((String)st.pop()).equals("<!DOCTYPE") )  {
1757
        validate = true;
1758
      }
1759
    }
1760

    
1761
    MetaCatUtil.debugMessage("Validation for dtd is " + validate, 10);
1762
    return validate;
1763
  }
1764
  // END OF INSERT/UPDATE SECTION
1765

    
1766
  /* check if the xml string contains key words to specify schema loocation*/
1767
  private boolean needSchemaValidation(StringReader xml) throws IOException
1768
  {
1769
    boolean needSchemaValidate =false;
1770
    if (xml == null)
1771
    {
1772
      MetaCatUtil.debugMessage("Validation for schema is " +
1773
                               needSchemaValidate, 10);
1774
      return needSchemaValidate;
1775
    }
1776
    System.out.println("before get target line");
1777
    String targetLine = getSchemaLine(xml);
1778
    System.out.println("before get target line");
1779
    // to see if the second line contain some keywords
1780
    if (targetLine != null && (targetLine.indexOf(SCHEMALOCATIONKEYWORD) != -1||
1781
             targetLine.indexOf(NONAMESPACELOCATION) != -1 ))
1782
    {
1783
      // if contains schema location key word, should be validate
1784
      needSchemaValidate = true;
1785
    }
1786

    
1787
    MetaCatUtil.debugMessage("Validation for schema is " +
1788
                             needSchemaValidate, 10);
1789
    return needSchemaValidate;
1790

    
1791
  }
1792

    
1793
   /* check if the xml string contains key words to specify schema loocation*/
1794
  private boolean needEml2Validation(StringReader xml) throws IOException
1795
  {
1796
    boolean needEml2Validate =false;
1797
    String emlNameSpace =DocumentImpl.EMLNAMESPACE;
1798
    String schemaLocationContent = null;
1799
    if (xml == null)
1800
    {
1801
      MetaCatUtil.debugMessage("Validation for schema is " +
1802
                               needEml2Validate, 10);
1803
      return needEml2Validate;
1804
    }
1805
    String targetLine = getSchemaLine(xml);
1806

    
1807
    if (targetLine != null)
1808
    {
1809
      
1810
      int startIndex = targetLine.indexOf(SCHEMALOCATIONKEYWORD);
1811
      int start = 1;
1812
      int end   = 1;
1813
      String schemaLocation = null;
1814
      int count = 0;
1815
      if (startIndex != -1)
1816
      {
1817
        for ( int i=startIndex; i<targetLine.length(); i++)
1818
        {
1819
          if (targetLine.charAt(i) =='"')
1820
          {
1821
            count ++;
1822
          }
1823
          if (targetLine.charAt(i) =='"' && count == 1)
1824
          {
1825
            start = i;
1826
          }
1827
          if (targetLine.charAt(i) =='"' && count == 2)
1828
          {
1829
            end = i;
1830
            break;
1831
          }
1832
        }
1833
      }
1834
      schemaLocation = targetLine.substring(start+1, end);
1835
      MetaCatUtil.debugMessage("schemaLocation in xml is: "+schemaLocation, 30);
1836
      if ( schemaLocation.indexOf(emlNameSpace) != -1)
1837
      {
1838
        needEml2Validate = true;
1839
      }
1840
    }
1841

    
1842
    MetaCatUtil.debugMessage("Validation for eml is " +
1843
                             needEml2Validate, 10);
1844
    return needEml2Validate;
1845

    
1846
  }
1847

    
1848
  private String getSchemaLine(StringReader xml) throws IOException
1849
  {
1850
    // find the line
1851
    String secondLine = null;
1852
    int count =0;
1853
    int endIndex = 0;
1854
    int startIndex = 0;
1855
    final int TARGETNUM = 2;
1856
    StringBuffer buffer = new StringBuffer();
1857
    boolean comment =false;
1858
    char thirdPreviousCharacter = '?';
1859
    char secondPreviousCharacter ='?';
1860
    char previousCharacter = '?';
1861
    char currentCharacter = '?';
1862
    
1863
    while ( (currentCharacter = (char) xml.read()) != -1)
1864
    {
1865
      //in a comment
1866
      if (currentCharacter =='-' && previousCharacter == '-'  && 
1867
          secondPreviousCharacter =='!' && thirdPreviousCharacter == '<')
1868
      {
1869
        comment = true;
1870
      }
1871
      //out of comment
1872
      if (comment && currentCharacter == '>' && previousCharacter == '-' && 
1873
          secondPreviousCharacter =='-')
1874
      {
1875
         comment = false;
1876
      }
1877
      
1878
      //this is not comment
1879
      if (currentCharacter !='!' && previousCharacter == '<' && !comment)
1880
      {
1881
        count ++;
1882
      }
1883
      // get target line
1884
      if (count == TARGETNUM && currentCharacter !='>')
1885
      {
1886
        buffer.append(currentCharacter);
1887
      }
1888
      if (count == TARGETNUM && currentCharacter == '>')
1889
      {
1890
          break;
1891
      }
1892
      thirdPreviousCharacter = secondPreviousCharacter;
1893
      secondPreviousCharacter = previousCharacter;
1894
      previousCharacter = currentCharacter;
1895
      
1896
    }
1897
    secondLine = buffer.toString();
1898
    MetaCatUtil.debugMessage("the second line string is: "+secondLine, 25);
1899
    xml.reset();
1900
    return secondLine;
1901
  }
1902

    
1903
  // DELETE SECTION
1904
  /**
1905
   * Handle the database delete request and delete an XML document
1906
   * from the database connection
1907
   */
1908
  private void handleDeleteAction(PrintWriter out, Hashtable params,
1909
               HttpServletResponse response, String user, String[] groups) {
1910

    
1911
    String[] docid = (String[])params.get("docid");
1912

    
1913
    // delete the document from the database
1914
    try {
1915

    
1916
                                      // NOTE -- NEED TO TEST HERE
1917
                                      // FOR EXISTENCE OF DOCID PARAM
1918
                                      // BEFORE ACCESSING ARRAY
1919
      try {
1920
        DocumentImpl.delete(docid[0], user, groups);
1921
        response.setContentType("text/xml");
1922
        out.println("<?xml version=\"1.0\"?>");
1923
        out.println("<success>");
1924
        out.println("Document deleted.");
1925
        out.println("</success>");
1926
      } catch (AccessionNumberException ane) {
1927
        response.setContentType("text/xml");
1928
        out.println("<?xml version=\"1.0\"?>");
1929
        out.println("<error>");
1930
        out.println("Error deleting document!!!");
1931
        out.println(ane.getMessage());
1932
        out.println("</error>");
1933
      }
1934
    } catch (Exception e) {
1935
      response.setContentType("text/xml");
1936
      out.println("<?xml version=\"1.0\"?>");
1937
      out.println("<error>");
1938
      out.println(e.getMessage());
1939
      out.println("</error>");
1940
    }
1941
  }
1942
  // END OF DELETE SECTION
1943

    
1944
  // VALIDATE SECTION
1945
  /**
1946
   * Handle the validation request and return the results to the requestor
1947
   */
1948
  private void handleValidateAction(PrintWriter out, Hashtable params) {
1949

    
1950
    // Get the document indicated
1951
    String valtext = null;
1952
    DBConnection dbConn = null;
1953
    int serialNumber = -1;
1954

    
1955
    try {
1956
      valtext = ((String[])params.get("valtext"))[0];
1957
    } catch (Exception nullpe) {
1958

    
1959

    
1960
      String docid = null;
1961
      try {
1962
        // Find the document id number
1963
        docid = ((String[])params.get("docid"))[0];
1964

    
1965

    
1966
        // Get the document indicated from the db
1967
        DocumentImpl xmldoc = new DocumentImpl(docid);
1968
        valtext = xmldoc.toString();
1969

    
1970
      } catch (NullPointerException npe) {
1971

    
1972
        out.println("<error>Error getting document ID: " + docid + "</error>");
1973
        //if ( conn != null ) { util.returnConnection(conn); }
1974
        return;
1975
      } catch (Exception e) {
1976

    
1977
        out.println(e.getMessage());
1978
      }
1979
    }
1980

    
1981

    
1982
    try {
1983
      // get a connection from the pool
1984
      dbConn=DBConnectionPool.
1985
                  getDBConnection("MetaCatServlet.handleValidateAction");
1986
      serialNumber=dbConn.getCheckOutSerialNumber();
1987
      DBValidate valobj = new DBValidate(saxparser,dbConn);
1988
      boolean valid = valobj.validateString(valtext);
1989

    
1990
      // set content type and other response header fields first
1991

    
1992
      out.println(valobj.returnErrors());
1993

    
1994
    } catch (NullPointerException npe2) {
1995
      // set content type and other response header fields first
1996

    
1997
      out.println("<error>Error validating document.</error>");
1998
    } catch (Exception e) {
1999

    
2000
      out.println(e.getMessage());
2001
    } finally {
2002
      // Return db connection
2003
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2004
    }
2005
  }
2006
  // END OF VALIDATE SECTION
2007

    
2008
  // OTHER ACTION HANDLERS
2009

    
2010
  /**
2011
   * Handle "getrevsionanddoctype" action
2012
   * Given a docid, return it's current revision and doctype from data base
2013
   * The output is String look like "rev;doctype"
2014
   */
2015
  private void handleGetRevisionAndDocTypeAction(PrintWriter out,
2016
                                                              Hashtable params)
2017
  {
2018
    // To store doc parameter
2019
    String [] docs = new String[10];
2020
    // Store a single doc id
2021
    String givenDocId = null;
2022
    // Get docid from parameters
2023
    if (params.containsKey("docid"))
2024
    {
2025
      docs = (String[])params.get("docid");
2026
    }
2027
    // Get first docid form string array
2028
    givenDocId = docs[0];
2029

    
2030
    try
2031
    {
2032
      // Make sure there is a docid
2033
      if (givenDocId == null || givenDocId.equals(""))
2034
      {
2035
        throw new Exception("User didn't specify docid!");
2036
      }//if
2037

    
2038
      // Create a DBUtil object
2039
      DBUtil dbutil = new DBUtil();
2040
      // Get a rev and doctype
2041
      String revAndDocType =
2042
                dbutil.getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
2043
      out.println(revAndDocType);
2044

    
2045
    }//try
2046
    catch (Exception e)
2047
    {
2048
      // Handle exception
2049
      out.println("<?xml version=\"1.0\"?>");
2050
      out.println("<error>");
2051
      out.println(e.getMessage());
2052
      out.println("</error>");
2053
    }//catch
2054

    
2055
  }//handleGetRevisionAndDocTypeAction
2056

    
2057
  /**
2058
   * Handle "getaccesscontrol" action.
2059
   * Read Access Control List from db connection in XML format
2060
   */
2061
  private void handleGetAccessControlAction(PrintWriter out, Hashtable params,
2062
                                       HttpServletResponse response,
2063
                                       String username, String[] groupnames) {
2064

    
2065
    DBConnection dbConn = null;
2066
    int serialNumber = -1;
2067
    String docid = ((String[])params.get("docid"))[0];
2068

    
2069
    try {
2070

    
2071
        // get connection from the pool
2072
        dbConn=DBConnectionPool.
2073
                 getDBConnection("MetaCatServlet.handleGetAccessControlAction");
2074
        serialNumber=dbConn.getCheckOutSerialNumber();
2075
        AccessControlList aclobj = new AccessControlList(dbConn);
2076
        String acltext = aclobj.getACL(docid, username, groupnames);
2077
        out.println(acltext);
2078

    
2079
    } catch (Exception e) {
2080
      out.println("<?xml version=\"1.0\"?>");
2081
      out.println("<error>");
2082
      out.println(e.getMessage());
2083
      out.println("</error>");
2084
    } finally {
2085
      // Retrun db connection to pool
2086
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2087
    }
2088

    
2089
  }
2090

    
2091
  /**
2092
   * Handle the "getprincipals" action.
2093
   * Read all principals from authentication scheme in XML format
2094
   */
2095
  private void handleGetPrincipalsAction(PrintWriter out, String user,
2096
                                         String password) {
2097

    
2098

    
2099
    try {
2100

    
2101

    
2102
        AuthSession auth = new AuthSession();
2103
        String principals = auth.getPrincipals(user, password);
2104
        out.println(principals);
2105

    
2106
    } catch (Exception e) {
2107
      out.println("<?xml version=\"1.0\"?>");
2108
      out.println("<error>");
2109
      out.println(e.getMessage());
2110
      out.println("</error>");
2111
    }
2112

    
2113
  }
2114

    
2115
  /**
2116
   * Handle "getdoctypes" action.
2117
   * Read all doctypes from db connection in XML format
2118
   */
2119
  private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
2120
                                       HttpServletResponse response) {
2121

    
2122

    
2123
    try {
2124

    
2125

    
2126
        DBUtil dbutil = new DBUtil();
2127
        String doctypes = dbutil.readDoctypes();
2128
        out.println(doctypes);
2129

    
2130
    } catch (Exception e) {
2131
      out.println("<?xml version=\"1.0\"?>");
2132
      out.println("<error>");
2133
      out.println(e.getMessage());
2134
      out.println("</error>");
2135
    }
2136

    
2137
  }
2138

    
2139
  /**
2140
   * Handle the "getdtdschema" action.
2141
   * Read DTD or Schema file for a given doctype from Metacat catalog system
2142
   */
2143
  private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
2144
                                        HttpServletResponse response) {
2145

    
2146

    
2147
    String doctype = null;
2148
    String[] doctypeArr = (String[])params.get("doctype");
2149

    
2150
    // get only the first doctype specified in the list of doctypes
2151
    // it could be done for all doctypes in that list
2152
    if (doctypeArr != null) {
2153
        doctype = ((String[])params.get("doctype"))[0];
2154
    }
2155

    
2156
    try {
2157

    
2158

    
2159
        DBUtil dbutil = new DBUtil();
2160
        String dtdschema = dbutil.readDTDSchema(doctype);
2161
        out.println(dtdschema);
2162

    
2163
    } catch (Exception e) {
2164
      out.println("<?xml version=\"1.0\"?>");
2165
      out.println("<error>");
2166
      out.println(e.getMessage());
2167
      out.println("</error>");
2168
    }
2169

    
2170
  }
2171

    
2172
  /**
2173
   * Handle the "getdataguide" action.
2174
   * Read Data Guide for a given doctype from db connection in XML format
2175
   */
2176
  private void handleGetDataGuideAction(PrintWriter out, Hashtable params,
2177
                                        HttpServletResponse response) {
2178

    
2179

    
2180
    String doctype = null;
2181
    String[] doctypeArr = (String[])params.get("doctype");
2182

    
2183
    // get only the first doctype specified in the list of doctypes
2184
    // it could be done for all doctypes in that list
2185
    if (doctypeArr != null) {
2186
        doctype = ((String[])params.get("doctype"))[0];
2187
    }
2188

    
2189
    try {
2190

    
2191

    
2192
        DBUtil dbutil = new DBUtil();
2193
        String dataguide = dbutil.readDataGuide(doctype);
2194
        out.println(dataguide);
2195

    
2196
    } catch (Exception e) {
2197
      out.println("<?xml version=\"1.0\"?>");
2198
      out.println("<error>");
2199
      out.println(e.getMessage());
2200
      out.println("</error>");
2201
    }
2202

    
2203
  }
2204

    
2205
  /**
2206
   * Handle the "getlastdocid" action.
2207
   * Get the latest docid with rev number from db connection in XML format
2208
   */
2209
  private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
2210
                                        HttpServletResponse response) {
2211

    
2212

    
2213
    String scope = ((String[])params.get("scope"))[0];
2214
    if (scope == null) {
2215
        scope = ((String[])params.get("username"))[0];
2216
    }
2217

    
2218
    try {
2219

    
2220

    
2221
        DBUtil dbutil = new DBUtil();
2222
        String lastDocid = dbutil.getMaxDocid(scope);
2223
        out.println("<?xml version=\"1.0\"?>");
2224
        out.println("<lastDocid>");
2225
        out.println("  <scope>" + scope + "</scope>");
2226
        out.println("  <docid>" + lastDocid + "</docid>");
2227
        out.println("</lastDocid>");
2228

    
2229
    } catch (Exception e) {
2230
      out.println("<?xml version=\"1.0\"?>");
2231
      out.println("<error>");
2232
      out.println(e.getMessage());
2233
      out.println("</error>");
2234
    }
2235

    
2236
  }
2237

    
2238
  /**
2239
   * Handle documents passed to metacat that are encoded using the
2240
   * "multipart/form-data" mime type.  This is typically used for uploading
2241
   * data files which may be binary and large.
2242
   */
2243
  private void handleMultipartForm(HttpServletRequest request,
2244
                                   HttpServletResponse response)
2245
  {
2246
    PrintWriter out = null;
2247
    String action = null;
2248

    
2249
    // Parse the multipart form, and save the parameters in a Hashtable and
2250
    // save the FileParts in a hashtable
2251

    
2252
    Hashtable params = new Hashtable();
2253
    Hashtable fileList = new Hashtable();
2254
    int sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit")))
2255
                                                                   .intValue();
2256
    MetaCatUtil.debugMessage("The limit size of data file is: "+sizeLimit, 50);
2257

    
2258
    try {
2259
      // MBJ: need to put filesize limit in Metacat config (metacat.properties)
2260
      MultipartParser mp = new MultipartParser(request, sizeLimit*1024*1024);
2261
      Part part;
2262
      while ((part = mp.readNextPart()) != null) {
2263
        String name = part.getName();
2264

    
2265
        if (part.isParam()) {
2266
          // it's a parameter part
2267
          ParamPart paramPart = (ParamPart) part;
2268
          String value = paramPart.getStringValue();
2269
          params.put(name, value);
2270
          if (name.equals("action")) {
2271
            action = value;
2272
          }
2273
        } else if (part.isFile()) {
2274
          // it's a file part
2275
          FilePart filePart = (FilePart) part;
2276
          fileList.put(name, filePart);
2277

    
2278
          // Stop once the first file part is found, otherwise going onto the
2279
          // next part prevents access to the file contents.  So...for upload
2280
          // to work, the datafile must be the last part
2281
          break;
2282
        }
2283
      }
2284
    } catch (IOException ioe) {
2285
      try {
2286
        out = response.getWriter();
2287
      } catch (IOException ioe2) {
2288
        System.err.println("Fatal Error: couldn't get response output stream.");
2289
      }
2290
      out.println("<?xml version=\"1.0\"?>");
2291
      out.println("<error>");
2292
      out.println("Error: problem reading multipart data.");
2293
      out.println("</error>");
2294
    }
2295

    
2296
    // Get the session information
2297
    String username = null;
2298
    String password = null;
2299
    String[] groupnames = null;
2300
    String sess_id = null;
2301

    
2302
    // be aware of session expiration on every request
2303
    HttpSession sess = request.getSession(true);
2304
    if (sess.isNew()) {
2305
      // session expired or has not been stored b/w user requests
2306
      username = "public";
2307
      sess.setAttribute("username", username);
2308
    } else {
2309
      username = (String)sess.getAttribute("username");
2310
      password = (String)sess.getAttribute("password");
2311
      groupnames = (String[])sess.getAttribute("groupnames");
2312
      try {
2313
        sess_id = (String)sess.getId();
2314
      } catch(IllegalStateException ise) {
2315
        System.out.println("error in  handleMultipartForm: this shouldn't " +
2316
                           "happen: the session should be valid: " +
2317
                           ise.getMessage());
2318
      }
2319
    }
2320

    
2321
    // Get the out stream
2322
    try {
2323
          out = response.getWriter();
2324
        } catch (IOException ioe2) {
2325
          util.debugMessage("Fatal Error: couldn't get response "+
2326
                             "output stream.", 30);
2327
        }
2328

    
2329
    if ( action.equals("upload")) {
2330
      if (username != null &&  !username.equals("public")) {
2331
        handleUploadAction(request, out, params, fileList,
2332
                           username, groupnames);
2333
      } else {
2334

    
2335
        out.println("<?xml version=\"1.0\"?>");
2336
        out.println("<error>");
2337
        out.println("Permission denied for " + action);
2338
        out.println("</error>");
2339
      }
2340
    } else {
2341
      /*try {
2342
        out = response.getWriter();
2343
      } catch (IOException ioe2) {
2344
        System.err.println("Fatal Error: couldn't get response output stream.");
2345
      }*/
2346
      out.println("<?xml version=\"1.0\"?>");
2347
      out.println("<error>");
2348
      out.println("Error: action not registered.  Please report this error.");
2349
      out.println("</error>");
2350
    }
2351
    out.close();
2352
  }
2353

    
2354
  /**
2355
   * Handle the upload action by saving the attached file to disk and
2356
   * registering it in the Metacat db
2357
   */
2358
  private void handleUploadAction(HttpServletRequest request,
2359
                                  PrintWriter out,
2360
                                  Hashtable params, Hashtable fileList,
2361
                                  String username, String[] groupnames)
2362
  {
2363
    //PrintWriter out = null;
2364
    //Connection conn = null;
2365
    String action = null;
2366
    String docid = null;
2367

    
2368
    /*response.setContentType("text/xml");
2369
    try
2370
    {
2371
      out = response.getWriter();
2372
    }
2373
    catch (IOException ioe2)
2374
    {
2375
      System.err.println("Fatal Error: couldn't get response output stream.");
2376
    }*/
2377

    
2378
    if (params.containsKey("docid"))
2379
    {
2380
      docid = (String)params.get("docid");
2381
    }
2382

    
2383
    // Make sure we have a docid and datafile
2384
    if (docid != null && fileList.containsKey("datafile")) {
2385

    
2386
      // Get a reference to the file part of the form
2387
      FilePart filePart = (FilePart)fileList.get("datafile");
2388
      String fileName = filePart.getFileName();
2389
      MetaCatUtil.debugMessage("Uploading filename: " + fileName, 10);
2390

    
2391
      // Check if the right file existed in the uploaded data
2392
      if (fileName != null) {
2393

    
2394
        try
2395
        {
2396
           //MetaCatUtil.debugMessage("Upload datafile " + docid +"...", 10);
2397
           //If document get lock data file grant
2398
           if (DocumentImpl.getDataFileLockGrant(docid))
2399
           {
2400
              // register the file in the database (which generates an exception
2401
              //if the docid is not acceptable or other untoward things happen
2402
              DocumentImpl.registerDocument(fileName, "BIN", docid, username);
2403

    
2404
              // Save the data file to disk using "docid" as the name
2405
              dataDirectory.mkdirs();
2406
              File newFile = new File(dataDirectory, docid);
2407
              long size = filePart.writeTo(newFile);
2408

    
2409
              // Force replication this data file
2410
              // To data file, "insert" and update is same
2411
              // The fourth parameter is null. Because it is notification server
2412
              // and this method is in MetaCatServerlet. It is original command,
2413
              // not get force replication info from another metacat
2414
              ForceReplicationHandler frh = new ForceReplicationHandler
2415
                                                (docid, "insert", false, null);
2416

    
2417
              // set content type and other response header fields first
2418
              out.println("<?xml version=\"1.0\"?>");
2419
              out.println("<success>");
2420
              out.println("<docid>" + docid + "</docid>");
2421
              out.println("<size>" + size + "</size>");
2422
              out.println("</success>");
2423
          }//if
2424

    
2425
        } //try
2426
        catch (Exception e)
2427
        {
2428
          out.println("<?xml version=\"1.0\"?>");
2429
          out.println("<error>");
2430
          out.println(e.getMessage());
2431
          out.println("</error>");
2432
        }
2433

    
2434
      }
2435
      else
2436
      {
2437
        // the field did not contain a file
2438
        out.println("<?xml version=\"1.0\"?>");
2439
        out.println("<error>");
2440
        out.println("The uploaded data did not contain a valid file.");
2441
        out.println("</error>");
2442
      }
2443
    }
2444
    else
2445
    {
2446
      // Error bcse docid missing or file missing
2447
      out.println("<?xml version=\"1.0\"?>");
2448
      out.println("<error>");
2449
      out.println("The uploaded data did not contain a valid docid " +
2450
                  "or valid file.");
2451
      out.println("</error>");
2452
    }
2453
  }
2454

    
2455
  /*
2456
   * A method to handle set access action
2457
   */
2458
  private void handleSetAccessAction(PrintWriter out,
2459
                                   Hashtable params,
2460
                                   String username)
2461
  {
2462
    String [] docList        = null;
2463
    String [] principalList  = null;
2464
    String [] permissionList = null;
2465
    String [] permTypeList   = null;
2466
    String [] permOrderList  = null;
2467
    String permission = null;
2468
    String permType   = null;
2469
    String permOrder  = null;
2470
    Vector errorList  = new Vector();
2471
    String error      = null;
2472
    Vector successList = new Vector();
2473
    String success    = null;
2474

    
2475

    
2476
    // Get parameters
2477
    if (params.containsKey("docid"))
2478
    {
2479
      docList = (String[])params.get("docid");
2480
    }
2481
    if (params.containsKey("principal"))
2482
    {
2483
      principalList = (String[])params.get("principal");
2484
    }
2485
    if (params.containsKey("permission"))
2486
    {
2487
      permissionList = (String[])params.get("permission");
2488

    
2489
    }
2490
    if (params.containsKey("permType"))
2491
    {
2492
      permTypeList = (String[])params.get("permType");
2493

    
2494
    }
2495
    if (params.containsKey("permOrder"))
2496
    {
2497
      permOrderList = (String[])params.get("permOrder");
2498

    
2499
    }
2500

    
2501
    // Make sure the parameter is not null
2502
    if (docList == null || principalList == null || permTypeList == null ||
2503
        permissionList == null)
2504
    {
2505
      error = "Please check your parameter list, it should look like: "+
2506
              "?action=setaccess&docid=pipeline.1.1&principal=public" +
2507
              "&permission=read&permType=allow&permOrder=allowFirst";
2508
      errorList.addElement(error);
2509
      outputResponse(successList, errorList, out);
2510
      return;
2511
    }
2512

    
2513
    // Only select first element for permission, type and order
2514
    permission = permissionList[0];
2515
    permType = permTypeList[0];
2516
    if (permOrderList != null)
2517
    {
2518
       permOrder = permOrderList[0];
2519
    }
2520

    
2521
    // Get package doctype set
2522
    Vector packageSet =MetaCatUtil.getOptionList(
2523
                                    MetaCatUtil.getOption("packagedoctypeset"));
2524
    //debug
2525
    if (packageSet != null)
2526
    {
2527
      for (int i = 0; i<packageSet.size(); i++)
2528
      {
2529
        MetaCatUtil.debugMessage("doctype in package set: " +
2530
                              (String)packageSet.elementAt(i), 34);
2531
      }
2532
    }//if
2533

    
2534
    // handle every accessionNumber
2535
    for (int i=0; i <docList.length; i++)
2536
    {
2537
      String accessionNumber = docList[i];
2538
      String owner = null;
2539
      String publicId = null;
2540
      // Get document owner and public id
2541
      try
2542
      {
2543
        owner = getFieldValueForDoc(accessionNumber, "user_owner");
2544
        publicId = getFieldValueForDoc(accessionNumber, "doctype");
2545
      }//try
2546
      catch (Exception e)
2547
      {
2548
        MetaCatUtil.debugMessage("Error in handleSetAccessAction: " +
2549
                                  e.getMessage(), 30);
2550
        error = "Error in set access control for document - " + accessionNumber+
2551
                 e.getMessage();
2552
        errorList.addElement(error);
2553
        continue;
2554
      }
2555
      //check if user is the owner. Only owner can do owner
2556
      if (username == null || owner == null || !username.equals(owner))
2557
      {
2558
        error = "User - " + username + " does not have permission to set " +
2559
                "access control for docid - " + accessionNumber;
2560
        errorList.addElement(error);
2561
        continue;
2562
      }
2563

    
2564
      // If docid publicid is BIN data file or other beta4, 6 package document
2565
      // we could not do set access control. Because we don't want inconsistent
2566
      // to its access docuemnt
2567
      if (publicId!=null && packageSet!=null && packageSet.contains(publicId))
2568
      {
2569
        error = "Could not set access control to document "+ accessionNumber +
2570
                "because it is in a pakcage and it has a access file for it";
2571
        errorList.addElement(error);
2572
        continue;
2573
      }
2574

    
2575
      // for every principle
2576
      for (int j = 0; j<principalList.length; j++)
2577
      {
2578
        String principal = principalList[j];
2579
        try
2580
        {
2581
          //insert permission
2582
          AccessControlForSingleFile accessControl = new
2583
                           AccessControlForSingleFile(accessionNumber,
2584
                                    principal, permission, permType, permOrder);
2585
          accessControl.insertPermissions();
2586
          success = "Set access control to document "+ accessionNumber +
2587
                    " successfully";
2588
          successList.addElement(success);
2589
        }
2590
        catch (Exception ee)
2591
        {
2592
          MetaCatUtil.debugMessage("Erorr in handleSetAccessAction2: " +
2593
                                   ee.getMessage(), 30);
2594
          error = "Faild to set access control for document " +
2595
                  accessionNumber + " because " + ee.getMessage();
2596
          errorList.addElement(error);
2597
          continue;
2598
        }
2599
      }//for every principle
2600
    }//for every document
2601
    outputResponse(successList, errorList, out);
2602
  }//handleSetAccessAction
2603

    
2604

    
2605
  /*
2606
   * A method try to determin a docid's public id, if couldn't find null
2607
   * will be returned.
2608
   */
2609
  private String getFieldValueForDoc(String accessionNumber, String fieldName)
2610
                                      throws Exception
2611
  {
2612
    if (accessionNumber==null || accessionNumber.equals("") ||fieldName == null
2613
        || fieldName.equals(""))
2614
    {
2615
      throw new Exception("Docid or field name was not specified");
2616
    }
2617

    
2618
    PreparedStatement pstmt = null;
2619
    ResultSet rs = null;
2620
    String fieldValue = null;
2621
    String docId = null;
2622
    DBConnection conn = null;
2623
    int serialNumber = -1;
2624

    
2625
    // get rid of revision if access number has
2626
    docId = MetaCatUtil.getDocIdFromString(accessionNumber);
2627
    try
2628
    {
2629
      //check out DBConnection
2630
      conn=DBConnectionPool.getDBConnection("MetaCatServlet.getPublicIdForDoc");
2631
      serialNumber=conn.getCheckOutSerialNumber();
2632
      pstmt = conn.prepareStatement(
2633
            "SELECT " + fieldName + " FROM xml_documents " +
2634
            "WHERE docid = ? ");
2635

    
2636
      pstmt.setString(1, docId);
2637
      pstmt.execute();
2638
      rs = pstmt.getResultSet();
2639
      boolean hasRow = rs.next();
2640
      int perm = 0;
2641
      if ( hasRow )
2642
      {
2643
        fieldValue = rs.getString(1);
2644
      }
2645
      else
2646
      {
2647
        throw new Exception("Could not find document: "+accessionNumber);
2648
      }
2649
    }//try
2650
    catch (Exception e)
2651
    {
2652
      MetaCatUtil.debugMessage("Exception in MetacatServlet.getPublicIdForDoc: "
2653
                               + e.getMessage(), 30);
2654
      throw e;
2655
    }
2656
    finally
2657
    {
2658
      try
2659
      {
2660
        rs.close();
2661
        pstmt.close();
2662

    
2663
      }
2664
      finally
2665
      {
2666
        DBConnectionPool.returnDBConnection(conn, serialNumber);
2667
      }
2668
    }
2669
    return fieldValue;
2670
  }//getFieldValueForDoc
2671

    
2672
  /*
2673
   * A method to output setAccess action result
2674
   */
2675
  private void outputResponse(Vector successList,
2676
                              Vector errorList,
2677
                              PrintWriter out)
2678
  {
2679
    boolean error = false;
2680
    boolean success = false;
2681
    // Output prolog
2682
    out.println(PROLOG);
2683
    // output success message
2684
    if ( successList != null)
2685
    {
2686
      for (int i = 0; i<successList.size(); i++)
2687
      {
2688
        out.println(SUCCESS);
2689
        out.println((String)successList.elementAt(i));
2690
        out.println(SUCCESSCLOSE);
2691
        success = true;
2692
      }//for
2693
    }//if
2694
    // output error message
2695
    if (errorList != null)
2696
    {
2697
      for (int i = 0; i<errorList.size(); i++)
2698
      {
2699
        out.println(ERROR);
2700
        out.println((String)errorList.elementAt(i));
2701
        out.println(ERRORCLOSE);
2702
        error = true;
2703
      }//for
2704
    }//if
2705

    
2706
    // if no error and no success info, send a error that nothing happened
2707
    if( !error && !success)
2708
    {
2709
      out.println(ERROR);
2710
      out.println("Nothing happend for setaccess action");
2711
      out.println(ERRORCLOSE);
2712
    }
2713

    
2714
  }//outputResponse
2715
}
(39-39/58)