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-09-04 15:22:21 -0700 (Thu, 04 Sep 2003) $'
11
 * '$Revision: 1816 $'
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
       // Now that we know the session is valid, we can delegate the request
337
      // to a particular action handler
338
      if(action.equals("query")) {
339
        PrintWriter out = response.getWriter();
340
        handleQuery(out,params,response,username,groupnames,sess_id);
341
        out.close();
342
      } else if(action.equals("squery")) {
343
        PrintWriter out = response.getWriter();
344
        if(params.containsKey("query")) {
345
         handleSQuery(out, params,response,username,groupnames,sess_id);
346
         out.close();
347
        } else {
348
          out.println("Illegal action squery without \"query\" parameter");
349
          out.close();
350
        }
351
      } else if (action.equals("export")) {
352

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

    
462
      //util.closeConnections();
463
      // Close the stream to the client
464
      //out.close();
465
    }
466
  }
467

    
468
  // LOGIN & LOGOUT SECTION
469
  /**
470
   * Handle the login request. Create a new session object.
471
   * Do user authentication through the session.
472
   */
473
  private void handleLoginAction(PrintWriter out, Hashtable params,
474
               HttpServletRequest request, HttpServletResponse response) {
475

    
476
    AuthSession sess = null;
477
    String un = ((String[])params.get("username"))[0];
478
    String pw = ((String[])params.get("password"))[0];
479
    String action = ((String[])params.get("action"))[0];
480
    String qformat = ((String[])params.get("qformat"))[0];
481

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

    
497
      try {
498

    
499
        DBTransform trans = new DBTransform();
500
        response.setContentType("text/html");
501
        trans.transformXMLDocument(sess.getMessage(), "-//NCEAS//login//EN",
502
                                   "-//W3C//HTML//EN", qformat, out, null);
503

    
504
      } catch(Exception e) {
505

    
506
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLoginAction: "
507
                                +e.getMessage(), 30);
508
      }
509

    
510
    // any output is returned
511
    }
512
  }
513

    
514
  /**
515
   * Handle the logout request. Close the connection.
516
   */
517
  private void handleLogoutAction(PrintWriter out, Hashtable params,
518
               HttpServletRequest request, HttpServletResponse response) {
519

    
520
    String qformat = ((String[])params.get("qformat"))[0];
521

    
522
    // close the connection
523
    HttpSession sess = request.getSession(false);
524
    if (sess != null) { sess.invalidate();  }
525

    
526
    // produce output
527
    StringBuffer output = new StringBuffer();
528
    output.append("<?xml version=\"1.0\"?>");
529
    output.append("<logout>");
530
    output.append("User logged out");
531
    output.append("</logout>");
532

    
533
    //format and transform the output
534
    if (qformat.equals("xml")) {
535
      response.setContentType("text/xml");
536
      out.println(output.toString());
537
    } else {
538

    
539
      try {
540

    
541
        DBTransform trans = new DBTransform();
542
        response.setContentType("text/html");
543
        trans.transformXMLDocument(output.toString(), "-//NCEAS//login//EN",
544
                                   "-//W3C//HTML//EN", qformat, out, null);
545

    
546
      } catch(Exception e) {
547

    
548
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLogoutAction"
549
                                  +e.getMessage(), 30);
550
      }
551
    }
552
  }
553
  // END OF LOGIN & LOGOUT SECTION
554

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

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

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

    
615
    resultdoc = createResultDocument(doclist, transformQuery(params));
616

    
617
    //format and transform the results
618
    if(qformat.equals("xml")) {
619
      response.setContentType("text/xml");
620
      out.println(resultdoc);
621
    } else {
622
      transformResultset(resultdoc, response, out, qformat, sessionid);
623
    }
624
  }
625

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

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

    
675
  /**
676
   * Run the query and return a hashtable of results.
677
   *
678
   * @param xmlquery the query to run
679
   */
680
  private Hashtable runQuery(String xmlquery, String user, String[] groups)
681
  {
682
    Hashtable doclist=null;
683

    
684
    try
685
    {
686

    
687
      DBQuery queryobj = new DBQuery(saxparser);
688
      doclist = queryobj.findDocuments(new StringReader(xmlquery),user,groups);
689

    
690
      return doclist;
691
    }
692
    catch (Exception e)
693
    {
694

    
695
      MetaCatUtil.debugMessage("Error in MetacatServlet.runQuery: "
696
                                                      + e.getMessage(), 30);
697
      doclist = null;
698
      return doclist;
699
    }
700
  }
701

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

    
717
    try {
718

    
719
      DBTransform trans = new DBTransform();
720
      response.setContentType("text/html");
721
      trans.transformXMLDocument(resultdoc, "-//NCEAS//resultset//EN",
722
                                 "-//W3C//HTML//EN", qformat, out, null,
723
                                 sessionid);
724

    
725
    }
726
    catch(Exception e)
727
    {
728

    
729
      MetaCatUtil.debugMessage("Error in MetaCatServlet.transformResultset:"
730
                                +e.getMessage(), 30);
731
    }
732
  }
733

    
734
  /**
735
   * Transforms a hashtable of documents to an xml or html result.
736
   *
737
   * @param doclist- the hashtable to transform
738
   * @param xmlquery- the query that returned the doclist result
739
   */
740
  protected String createResultDocument(Hashtable doclist, String xmlquery)
741
  {
742
    // Create a buffer to hold the xml result
743
    StringBuffer resultset = new StringBuffer();
744

    
745
    // Print the resulting root nodes
746
    String docid = null;
747
    String document = null;
748
    resultset.append("<?xml version=\"1.0\"?>\n");
749
    resultset.append("<resultset>\n");
750

    
751
    resultset.append("  <query>" + xmlquery + "</query>");
752

    
753
    if(doclist != null)
754
    {
755
      Enumeration doclistkeys = doclist.keys();
756
      while (doclistkeys.hasMoreElements())
757
      {
758
        docid = (String)doclistkeys.nextElement();
759
        document = (String)doclist.get(docid);
760
        resultset.append("  <document>" + document + "</document>");
761
      }
762
    }
763

    
764
    resultset.append("</resultset>");
765
    return resultset.toString();
766
  }
767
  // END OF SQUERY & QUERY SECTION
768

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

    
787
    String[] docs = new String[10];
788
    String docId = "";
789

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

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

    
856
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleExportAction: " +
857
                         e.getMessage(), 30);
858
      e.printStackTrace(System.out);
859

    
860
    }//catch
861

    
862
  }//handleExportAction
863

    
864

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

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

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

    
921
      }//else
922

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

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

    
972
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleReadInlineDataAction: "
973
                                + e.getMessage(), 30);
974

    
975
    }//catch
976

    
977
  }//handleReadInlineDataAction
978

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

    
996
    try
997
    {
998
      //check out DBConnection
999
      conn=DBConnectionPool.getDBConnection("AccessControlList.isAllowFirst");
1000
      serialNumber=conn.getCheckOutSerialNumber();
1001

    
1002
      pStmt = conn.prepareStatement(sql);
1003
      //bind value
1004
      pStmt.setString(1, docId);//docid
1005
      pStmt.setString(2, inLineDataId);//inlinedataid
1006
      pStmt.setString(3, docId);
1007
      // excute query
1008
      pStmt.execute();
1009
      ResultSet rs = pStmt.getResultSet();
1010
      hasRow=rs.next();
1011
      // get result
1012
      if (hasRow)
1013
      {
1014
        nodeId = rs.getLong(1);
1015
      }//if
1016

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

    
1038

    
1039

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

    
1061
    try {
1062
      String[] docs = new String[0];
1063
      String docid = "";
1064
      String qformat = "";
1065
      String abstrpath = null;
1066

    
1067
      // read the params
1068
      if (params.containsKey("docid")) {
1069
        docs = (String[])params.get("docid");
1070
      }
1071
      if (params.containsKey("qformat")) {
1072
        qformat = ((String[])params.get("qformat"))[0];
1073
      }
1074
      // the param for only metadata (eml)
1075
      if (params.containsKey("inlinedata"))
1076
      {
1077

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

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

    
1115
          // case docid="http://.../filename"
1116
          } else {
1117
            docid = docs[i];
1118
            if ( zip ) {
1119
              addDocToZip(docid, zout, user, groups);
1120
            } else {
1121
              readFromURLConnection(response, docid);
1122
            }
1123
          }
1124

    
1125
        // case docid="ccc"
1126
        } catch (MalformedURLException mue) {
1127
          docid = docs[i];
1128
          if ( zip ) {
1129
            addDocToZip(docid, zout, user, groups);
1130
          } else {
1131
            readFromMetacat(response, docid, qformat, abstrpath,
1132
                            user, groups, zip, zout, withInlineData, params);
1133
          }
1134
        }
1135

    
1136
      } /* end for */
1137

    
1138
      if ( zip ) {
1139
        zout.finish(); //terminate the zip file
1140
        zout.close();  //close the zip stream
1141
      }
1142

    
1143

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

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

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

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

    
1246
        }
1247
        // Close zip output stream
1248
        if ( zout != null ) { zout.close(); }
1249

    
1250
      } catch (IOException ioe) {
1251
        MetaCatUtil.debugMessage("Problem with the servlet output " +
1252
                           "in MetacatServlet.handleReadAction: " +
1253
                           ioe.getMessage(), 30);
1254
        ioe.printStackTrace(System.out);
1255

    
1256
      }
1257

    
1258
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleReadAction: " +
1259
                               e.getMessage(), 30);
1260
      //e.printStackTrace(System.out);
1261
    }
1262

    
1263
  }
1264

    
1265
  // read metadata or data from Metacat
1266
  private void readFromMetacat(HttpServletResponse response, String docid,
1267
                               String qformat, String abstrpath, String user,
1268
                               String[] groups, boolean zip,
1269
                               ZipOutputStream zout, boolean withInlineData,
1270
                               Hashtable params)
1271
               throws ClassNotFoundException, IOException, SQLException,
1272
                      McdbException, Exception
1273
  {
1274

    
1275
    try {
1276

    
1277

    
1278
      DocumentImpl doc = new DocumentImpl(docid);
1279

    
1280
      //check the permission for read
1281
      if (!doc.hasReadPermission(user, groups, docid))
1282
      {
1283
        Exception e = new Exception("User " + user + " does not have permission"
1284
                       +" to read the document with the docid " + docid);
1285

    
1286
        throw e;
1287
      }
1288

    
1289
      if ( doc.getRootNodeID() == 0 ) {
1290
        // this is data file
1291
        String filepath = util.getOption("datafilepath");
1292
        if(!filepath.endsWith("/")) {
1293
          filepath += "/";
1294
        }
1295
        String filename = filepath + docid;
1296
        FileInputStream fin = null;
1297
        fin = new FileInputStream(filename);
1298

    
1299
        //MIME type
1300
        String contentType = getServletContext().getMimeType(filename);
1301
        if (contentType == null)
1302
        {
1303
          ContentTypeProvider provider = new ContentTypeProvider(docid);
1304
          contentType = provider.getContentType();
1305
          MetaCatUtil.debugMessage("Final contenttype is: "+ contentType, 30);
1306
        }
1307

    
1308
        response.setContentType(contentType);
1309
        // if we decide to use "application/octet-stream" for all data returns
1310
        // response.setContentType("application/octet-stream");
1311

    
1312
        try {
1313

    
1314
          ServletOutputStream out = response.getOutputStream();
1315
          byte[] buf = new byte[4 * 1024]; // 4K buffer
1316
          int b = fin.read(buf);
1317
          while (b != -1) {
1318
            out.write(buf, 0, b);
1319
            b = fin.read(buf);
1320
          }
1321
        } finally {
1322
          if (fin != null) fin.close();
1323
        }
1324

    
1325
      } else {
1326
        // this is metadata doc
1327
        if ( qformat.equals("xml") ) {
1328

    
1329
          // set content type first
1330
          response.setContentType("text/xml");   //MIME type
1331
          PrintWriter out = response.getWriter();
1332
          doc.toXml(out, user, groups, withInlineData);
1333
        } else {
1334
          response.setContentType("text/html");  //MIME type
1335
          PrintWriter out = response.getWriter();
1336

    
1337
          // Look up the document type
1338
          String doctype = doc.getDoctype();
1339
          // Transform the document to the new doctype
1340
          DBTransform dbt = new DBTransform();
1341
          dbt.transformXMLDocument(doc.toString(user, groups, withInlineData),
1342
                                   doctype,"-//W3C//HTML//EN",
1343
                                   qformat, out, params);
1344
        }
1345

    
1346
      }
1347
    }
1348
    catch (Exception except)
1349
    {
1350
      throw except;
1351

    
1352
    }
1353

    
1354
  }
1355

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

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

    
1401
  }
1402

    
1403
  // read file/doc and write to ZipOutputStream
1404
  private void addDocToZip(String docid, ZipOutputStream zout,
1405
                              String user, String[] groups)
1406
               throws ClassNotFoundException, IOException, SQLException,
1407
                      McdbException, Exception
1408
  {
1409
    byte[] bytestring = null;
1410
    ZipEntry zentry = null;
1411

    
1412
    try {
1413
      URL url = new URL(docid);
1414

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

    
1432
    } catch (MalformedURLException mue) {
1433

    
1434
      // this is metacat doc (data file or metadata doc)
1435

    
1436
      try {
1437

    
1438
        DocumentImpl doc = new DocumentImpl(docid);
1439

    
1440
        //check the permission for read
1441
        if (!doc.hasReadPermission(user, groups, docid))
1442
        {
1443
          Exception e = new Exception("User " + user + " does not have "
1444
                    +"permission to read the document with the docid " + docid);
1445

    
1446
          throw e;
1447
        }
1448

    
1449
        if ( doc.getRootNodeID() == 0 ) {
1450
          // this is data file; add file to zip
1451
          String filepath = util.getOption("datafilepath");
1452
          if(!filepath.endsWith("/")) {
1453
            filepath += "/";
1454
          }
1455
          String filename = filepath + docid;
1456
          FileInputStream fin = null;
1457
          fin = new FileInputStream(filename);
1458
          try {
1459

    
1460
            zentry = new ZipEntry(docid);
1461
            zout.putNextEntry(zentry);
1462
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1463
            int b = fin.read(buf);
1464
            while (b != -1) {
1465
              zout.write(buf, 0, b);
1466
              b = fin.read(buf);
1467
            }
1468
          } finally {
1469
            if (fin != null) fin.close();
1470
          }
1471
          zout.closeEntry();
1472

    
1473
        } else {
1474
          // this is metadata doc; add doc to zip
1475
          bytestring = doc.toString().getBytes();
1476
          zentry = new ZipEntry(docid + ".xml");
1477
          zentry.setSize(bytestring.length);
1478
          zout.putNextEntry(zentry);
1479
          zout.write(bytestring, 0, bytestring.length);
1480
          zout.closeEntry();
1481
        }
1482
      } catch (Exception except) {
1483
        throw except;
1484

    
1485
      }
1486

    
1487
    }
1488

    
1489
  }
1490

    
1491
  // view abstract within document
1492
  private void viewAbstract(HttpServletResponse response,
1493
                            String abstractpath, String docid)
1494
               throws ClassNotFoundException, IOException, SQLException,
1495
                      McdbException, Exception
1496
  {
1497

    
1498
    PrintWriter out =null;
1499
    try {
1500

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

    
1511
    } catch (Exception e) {
1512
       out.println("<?xml version=\"1.0\"?>");
1513
       out.println("<error>");
1514
       out.println(e.getMessage());
1515
       out.println("</error>");
1516

    
1517

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

    
1557
  // END OF READ SECTION
1558

    
1559

    
1560

    
1561
  // INSERT/UPDATE SECTION
1562
  /**
1563
   * Handle the database putdocument request and write an XML document
1564
   * to the database connection
1565
   */
1566
  private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params,
1567
               String user, String[] groups) {
1568

    
1569
    DBConnection dbConn = null;
1570
    int serialNumber = -1;
1571

    
1572
    try {
1573
      // Get the document indicated
1574
      String[] doctext = (String[])params.get("doctext");
1575

    
1576
      String pub = null;
1577
      if (params.containsKey("public")) {
1578
        pub = ((String[])params.get("public"))[0];
1579
      }
1580

    
1581
      StringReader dtd = null;
1582
      if (params.containsKey("dtdtext")) {
1583
        String[] dtdtext = (String[])params.get("dtdtext");
1584
        try {
1585
          if ( !dtdtext[0].equals("") ) {
1586
            dtd = new StringReader(dtdtext[0]);
1587
          }
1588
        } catch (NullPointerException npe) {}
1589
      }
1590

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

    
1627
        String[] action = (String[])params.get("action");
1628
        String[] docid = (String[])params.get("docid");
1629
        String newdocid = null;
1630

    
1631
        String doAction = null;
1632
        if (action[0].equals("insert")) {
1633
          doAction = "INSERT";
1634
        } else if (action[0].equals("update")) {
1635
          doAction = "UPDATE";
1636
        }
1637

    
1638
        try
1639
        {
1640
          // get a connection from the pool
1641
          dbConn=DBConnectionPool.
1642
                  getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1643
          serialNumber=dbConn.getCheckOutSerialNumber();
1644

    
1645
           // write the document to the database
1646
          try
1647
          {
1648
            String accNumber = docid[0];
1649
            MetaCatUtil.debugMessage(""+ doAction + " " + accNumber +"...", 10);
1650
            if (accNumber.equals(""))
1651
            {
1652
              accNumber = null;
1653
            }//if
1654
            newdocid = documentWrapper.write(dbConn, xml, pub, dtd, doAction,
1655
                                          accNumber, user, groups);
1656

    
1657
          }//try
1658
          catch (NullPointerException npe)
1659
          {
1660
            newdocid = documentWrapper.write(dbConn, xml, pub, dtd, doAction,
1661
                                          null, user, groups);
1662
          }//catch
1663

    
1664
        }//try
1665
        finally
1666
        {
1667
          // Return db connection
1668
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1669
        }
1670

    
1671
        // set content type and other response header fields first
1672
        //response.setContentType("text/xml");
1673
        out.println("<?xml version=\"1.0\"?>");
1674
        out.println("<success>");
1675
        out.println("<docid>" + newdocid + "</docid>");
1676
        out.println("</success>");
1677

    
1678
      }
1679
      catch (NullPointerException npe)
1680
      {
1681
        //response.setContentType("text/xml");
1682
        out.println("<?xml version=\"1.0\"?>");
1683
        out.println("<error>");
1684
        out.println(npe.getMessage());
1685
        out.println("</error>");
1686
      }
1687
    }
1688
    catch (Exception e)
1689
    {
1690
      //response.setContentType("text/xml");
1691
      out.println("<?xml version=\"1.0\"?>");
1692
      out.println("<error>");
1693
      out.println(e.getMessage());
1694
      out.println("</error>");
1695
    }
1696
  }
1697

    
1698
  /**
1699
   * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1700
   * in order to decide whether to use validation parser
1701
   */
1702
  private static boolean needDTDValidation(StringReader xmlreader) throws 
1703
                                                             IOException 
1704
  {
1705

    
1706
    
1707
    StringBuffer cbuff = new StringBuffer();
1708
    java.util.Stack st = new java.util.Stack();
1709
    boolean validate = false;
1710
    int c;
1711
    int inx;
1712

    
1713
    // read from the stream until find the keywords
1714
    while ( (st.empty() || st.size()<4) && ((c = xmlreader.read()) != -1) ) {
1715
      cbuff.append((char)c);
1716

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

    
1741
    // close the stream
1742
    xmlreader.reset();
1743

    
1744
    // check the stack whether it contains the keywords:
1745
    // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1746
    if ( st.size() == 4 ) {
1747
      if ( ((String)st.pop()).equals(">") &&
1748
           ( ((String)st.peek()).equals("PUBLIC") |
1749
             ((String)st.pop()).equals("SYSTEM") ) &&
1750
           ((String)st.pop()).equals("<!DOCTYPE") )  {
1751
        validate = true;
1752
      }
1753
    }
1754

    
1755
    MetaCatUtil.debugMessage("Validation for dtd is " + validate, 10);
1756
    return validate;
1757
  }
1758
  // END OF INSERT/UPDATE SECTION
1759

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

    
1781
    MetaCatUtil.debugMessage("Validation for schema is " +
1782
                             needSchemaValidate, 10);
1783
    return needSchemaValidate;
1784

    
1785
  }
1786

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

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

    
1836
    MetaCatUtil.debugMessage("Validation for eml is " +
1837
                             needEml2Validate, 10);
1838
    return needEml2Validate;
1839

    
1840
  }
1841

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

    
1897
  // DELETE SECTION
1898
  /**
1899
   * Handle the database delete request and delete an XML document
1900
   * from the database connection
1901
   */
1902
  private void handleDeleteAction(PrintWriter out, Hashtable params,
1903
               HttpServletResponse response, String user, String[] groups) {
1904

    
1905
    String[] docid = (String[])params.get("docid");
1906

    
1907
    // delete the document from the database
1908
    try {
1909

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

    
1938
  // VALIDATE SECTION
1939
  /**
1940
   * Handle the validation request and return the results to the requestor
1941
   */
1942
  private void handleValidateAction(PrintWriter out, Hashtable params) {
1943

    
1944
    // Get the document indicated
1945
    String valtext = null;
1946
    DBConnection dbConn = null;
1947
    int serialNumber = -1;
1948

    
1949
    try {
1950
      valtext = ((String[])params.get("valtext"))[0];
1951
    } catch (Exception nullpe) {
1952

    
1953

    
1954
      String docid = null;
1955
      try {
1956
        // Find the document id number
1957
        docid = ((String[])params.get("docid"))[0];
1958

    
1959

    
1960
        // Get the document indicated from the db
1961
        DocumentImpl xmldoc = new DocumentImpl(docid);
1962
        valtext = xmldoc.toString();
1963

    
1964
      } catch (NullPointerException npe) {
1965

    
1966
        out.println("<error>Error getting document ID: " + docid + "</error>");
1967
        //if ( conn != null ) { util.returnConnection(conn); }
1968
        return;
1969
      } catch (Exception e) {
1970

    
1971
        out.println(e.getMessage());
1972
      }
1973
    }
1974

    
1975

    
1976
    try {
1977
      // get a connection from the pool
1978
      dbConn=DBConnectionPool.
1979
                  getDBConnection("MetaCatServlet.handleValidateAction");
1980
      serialNumber=dbConn.getCheckOutSerialNumber();
1981
      DBValidate valobj = new DBValidate(saxparser,dbConn);
1982
      boolean valid = valobj.validateString(valtext);
1983

    
1984
      // set content type and other response header fields first
1985

    
1986
      out.println(valobj.returnErrors());
1987

    
1988
    } catch (NullPointerException npe2) {
1989
      // set content type and other response header fields first
1990

    
1991
      out.println("<error>Error validating document.</error>");
1992
    } catch (Exception e) {
1993

    
1994
      out.println(e.getMessage());
1995
    } finally {
1996
      // Return db connection
1997
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1998
    }
1999
  }
2000
  // END OF VALIDATE SECTION
2001

    
2002
  // OTHER ACTION HANDLERS
2003

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

    
2024
    try
2025
    {
2026
      // Make sure there is a docid
2027
      if (givenDocId == null || givenDocId.equals(""))
2028
      {
2029
        throw new Exception("User didn't specify docid!");
2030
      }//if
2031

    
2032
      // Create a DBUtil object
2033
      DBUtil dbutil = new DBUtil();
2034
      // Get a rev and doctype
2035
      String revAndDocType =
2036
                dbutil.getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
2037
      out.println(revAndDocType);
2038

    
2039
    }//try
2040
    catch (Exception e)
2041
    {
2042
      // Handle exception
2043
      out.println("<?xml version=\"1.0\"?>");
2044
      out.println("<error>");
2045
      out.println(e.getMessage());
2046
      out.println("</error>");
2047
    }//catch
2048

    
2049
  }//handleGetRevisionAndDocTypeAction
2050

    
2051
  /**
2052
   * Handle "getaccesscontrol" action.
2053
   * Read Access Control List from db connection in XML format
2054
   */
2055
  private void handleGetAccessControlAction(PrintWriter out, Hashtable params,
2056
                                       HttpServletResponse response,
2057
                                       String username, String[] groupnames) {
2058

    
2059
    DBConnection dbConn = null;
2060
    int serialNumber = -1;
2061
    String docid = ((String[])params.get("docid"))[0];
2062

    
2063
    try {
2064

    
2065
        // get connection from the pool
2066
        dbConn=DBConnectionPool.
2067
                 getDBConnection("MetaCatServlet.handleGetAccessControlAction");
2068
        serialNumber=dbConn.getCheckOutSerialNumber();
2069
        AccessControlList aclobj = new AccessControlList(dbConn);
2070
        String acltext = aclobj.getACL(docid, username, groupnames);
2071
        out.println(acltext);
2072

    
2073
    } catch (Exception e) {
2074
      out.println("<?xml version=\"1.0\"?>");
2075
      out.println("<error>");
2076
      out.println(e.getMessage());
2077
      out.println("</error>");
2078
    } finally {
2079
      // Retrun db connection to pool
2080
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2081
    }
2082

    
2083
  }
2084

    
2085
  /**
2086
   * Handle the "getprincipals" action.
2087
   * Read all principals from authentication scheme in XML format
2088
   */
2089
  private void handleGetPrincipalsAction(PrintWriter out, String user,
2090
                                         String password) {
2091

    
2092

    
2093
    try {
2094

    
2095

    
2096
        AuthSession auth = new AuthSession();
2097
        String principals = auth.getPrincipals(user, password);
2098
        out.println(principals);
2099

    
2100
    } catch (Exception e) {
2101
      out.println("<?xml version=\"1.0\"?>");
2102
      out.println("<error>");
2103
      out.println(e.getMessage());
2104
      out.println("</error>");
2105
    }
2106

    
2107
  }
2108

    
2109
  /**
2110
   * Handle "getdoctypes" action.
2111
   * Read all doctypes from db connection in XML format
2112
   */
2113
  private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
2114
                                       HttpServletResponse response) {
2115

    
2116

    
2117
    try {
2118

    
2119

    
2120
        DBUtil dbutil = new DBUtil();
2121
        String doctypes = dbutil.readDoctypes();
2122
        out.println(doctypes);
2123

    
2124
    } catch (Exception e) {
2125
      out.println("<?xml version=\"1.0\"?>");
2126
      out.println("<error>");
2127
      out.println(e.getMessage());
2128
      out.println("</error>");
2129
    }
2130

    
2131
  }
2132

    
2133
  /**
2134
   * Handle the "getdtdschema" action.
2135
   * Read DTD or Schema file for a given doctype from Metacat catalog system
2136
   */
2137
  private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
2138
                                        HttpServletResponse response) {
2139

    
2140

    
2141
    String doctype = null;
2142
    String[] doctypeArr = (String[])params.get("doctype");
2143

    
2144
    // get only the first doctype specified in the list of doctypes
2145
    // it could be done for all doctypes in that list
2146
    if (doctypeArr != null) {
2147
        doctype = ((String[])params.get("doctype"))[0];
2148
    }
2149

    
2150
    try {
2151

    
2152

    
2153
        DBUtil dbutil = new DBUtil();
2154
        String dtdschema = dbutil.readDTDSchema(doctype);
2155
        out.println(dtdschema);
2156

    
2157
    } catch (Exception e) {
2158
      out.println("<?xml version=\"1.0\"?>");
2159
      out.println("<error>");
2160
      out.println(e.getMessage());
2161
      out.println("</error>");
2162
    }
2163

    
2164
  }
2165

    
2166
  /**
2167
   * Handle the "getdataguide" action.
2168
   * Read Data Guide for a given doctype from db connection in XML format
2169
   */
2170
  private void handleGetDataGuideAction(PrintWriter out, Hashtable params,
2171
                                        HttpServletResponse response) {
2172

    
2173

    
2174
    String doctype = null;
2175
    String[] doctypeArr = (String[])params.get("doctype");
2176

    
2177
    // get only the first doctype specified in the list of doctypes
2178
    // it could be done for all doctypes in that list
2179
    if (doctypeArr != null) {
2180
        doctype = ((String[])params.get("doctype"))[0];
2181
    }
2182

    
2183
    try {
2184

    
2185

    
2186
        DBUtil dbutil = new DBUtil();
2187
        String dataguide = dbutil.readDataGuide(doctype);
2188
        out.println(dataguide);
2189

    
2190
    } catch (Exception e) {
2191
      out.println("<?xml version=\"1.0\"?>");
2192
      out.println("<error>");
2193
      out.println(e.getMessage());
2194
      out.println("</error>");
2195
    }
2196

    
2197
  }
2198

    
2199
  /**
2200
   * Handle the "getlastdocid" action.
2201
   * Get the latest docid with rev number from db connection in XML format
2202
   */
2203
  private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
2204
                                        HttpServletResponse response) {
2205

    
2206

    
2207
    String scope = ((String[])params.get("scope"))[0];
2208
    if (scope == null) {
2209
        scope = ((String[])params.get("username"))[0];
2210
    }
2211

    
2212
    try {
2213

    
2214

    
2215
        DBUtil dbutil = new DBUtil();
2216
        String lastDocid = dbutil.getMaxDocid(scope);
2217
        out.println("<?xml version=\"1.0\"?>");
2218
        out.println("<lastDocid>");
2219
        out.println("  <scope>" + scope + "</scope>");
2220
        out.println("  <docid>" + lastDocid + "</docid>");
2221
        out.println("</lastDocid>");
2222

    
2223
    } catch (Exception e) {
2224
      out.println("<?xml version=\"1.0\"?>");
2225
      out.println("<error>");
2226
      out.println(e.getMessage());
2227
      out.println("</error>");
2228
    }
2229

    
2230
  }
2231

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

    
2243
    // Parse the multipart form, and save the parameters in a Hashtable and
2244
    // save the FileParts in a hashtable
2245

    
2246
    Hashtable params = new Hashtable();
2247
    Hashtable fileList = new Hashtable();
2248
    int sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit")))
2249
                                                                   .intValue();
2250
    MetaCatUtil.debugMessage("The limit size of data file is: "+sizeLimit, 50);
2251

    
2252
    try {
2253
      // MBJ: need to put filesize limit in Metacat config (metacat.properties)
2254
      MultipartParser mp = new MultipartParser(request, sizeLimit*1024*1024);
2255
      Part part;
2256
      while ((part = mp.readNextPart()) != null) {
2257
        String name = part.getName();
2258

    
2259
        if (part.isParam()) {
2260
          // it's a parameter part
2261
          ParamPart paramPart = (ParamPart) part;
2262
          String value = paramPart.getStringValue();
2263
          params.put(name, value);
2264
          if (name.equals("action")) {
2265
            action = value;
2266
          }
2267
        } else if (part.isFile()) {
2268
          // it's a file part
2269
          FilePart filePart = (FilePart) part;
2270
          fileList.put(name, filePart);
2271

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

    
2290
    // Get the session information
2291
    String username = null;
2292
    String password = null;
2293
    String[] groupnames = null;
2294
    String sess_id = null;
2295

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

    
2315
    // Get the out stream
2316
    try {
2317
          out = response.getWriter();
2318
        } catch (IOException ioe2) {
2319
          util.debugMessage("Fatal Error: couldn't get response "+
2320
                             "output stream.", 30);
2321
        }
2322

    
2323
    if ( action.equals("upload")) {
2324
      if (username != null &&  !username.equals("public")) {
2325
        handleUploadAction(request, out, params, fileList,
2326
                           username, groupnames);
2327
      } else {
2328

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

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

    
2362
    /*response.setContentType("text/xml");
2363
    try
2364
    {
2365
      out = response.getWriter();
2366
    }
2367
    catch (IOException ioe2)
2368
    {
2369
      System.err.println("Fatal Error: couldn't get response output stream.");
2370
    }*/
2371

    
2372
    if (params.containsKey("docid"))
2373
    {
2374
      docid = (String)params.get("docid");
2375
    }
2376

    
2377
    // Make sure we have a docid and datafile
2378
    if (docid != null && fileList.containsKey("datafile")) {
2379

    
2380
      // Get a reference to the file part of the form
2381
      FilePart filePart = (FilePart)fileList.get("datafile");
2382
      String fileName = filePart.getFileName();
2383
      MetaCatUtil.debugMessage("Uploading filename: " + fileName, 10);
2384

    
2385
      // Check if the right file existed in the uploaded data
2386
      if (fileName != null) {
2387

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

    
2398
              // Save the data file to disk using "docid" as the name
2399
              dataDirectory.mkdirs();
2400
              File newFile = new File(dataDirectory, docid);
2401
              long size = filePart.writeTo(newFile);
2402

    
2403
              // Force replication this data file
2404
              // To data file, "insert" and update is same
2405
              // The fourth parameter is null. Because it is notification server
2406
              // and this method is in MetaCatServerlet. It is original command,
2407
              // not get force replication info from another metacat
2408
              ForceReplicationHandler frh = new ForceReplicationHandler
2409
                                                (docid, "insert", false, null);
2410

    
2411
              // set content type and other response header fields first
2412
              out.println("<?xml version=\"1.0\"?>");
2413
              out.println("<success>");
2414
              out.println("<docid>" + docid + "</docid>");
2415
              out.println("<size>" + size + "</size>");
2416
              out.println("</success>");
2417
          }//if
2418

    
2419
        } //try
2420
        catch (Exception e)
2421
        {
2422
          out.println("<?xml version=\"1.0\"?>");
2423
          out.println("<error>");
2424
          out.println(e.getMessage());
2425
          out.println("</error>");
2426
        }
2427

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

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

    
2469

    
2470
    // Get parameters
2471
    if (params.containsKey("docid"))
2472
    {
2473
      docList = (String[])params.get("docid");
2474
    }
2475
    if (params.containsKey("principal"))
2476
    {
2477
      principalList = (String[])params.get("principal");
2478
    }
2479
    if (params.containsKey("permission"))
2480
    {
2481
      permissionList = (String[])params.get("permission");
2482

    
2483
    }
2484
    if (params.containsKey("permType"))
2485
    {
2486
      permTypeList = (String[])params.get("permType");
2487

    
2488
    }
2489
    if (params.containsKey("permOrder"))
2490
    {
2491
      permOrderList = (String[])params.get("permOrder");
2492

    
2493
    }
2494

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

    
2507
    // Only select first element for permission, type and order
2508
    permission = permissionList[0];
2509
    permType = permTypeList[0];
2510
    if (permOrderList != null)
2511
    {
2512
       permOrder = permOrderList[0];
2513
    }
2514

    
2515
    // Get package doctype set
2516
    Vector packageSet =MetaCatUtil.getOptionList(
2517
                                    MetaCatUtil.getOption("packagedoctypeset"));
2518
    //debug
2519
    if (packageSet != null)
2520
    {
2521
      for (int i = 0; i<packageSet.size(); i++)
2522
      {
2523
        MetaCatUtil.debugMessage("doctype in package set: " +
2524
                              (String)packageSet.elementAt(i), 34);
2525
      }
2526
    }//if
2527

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

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

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

    
2598

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

    
2612
    PreparedStatement pstmt = null;
2613
    ResultSet rs = null;
2614
    String fieldValue = null;
2615
    String docId = null;
2616
    DBConnection conn = null;
2617
    int serialNumber = -1;
2618

    
2619
    // get rid of revision if access number has
2620
    docId = MetaCatUtil.getDocIdFromString(accessionNumber);
2621
    try
2622
    {
2623
      //check out DBConnection
2624
      conn=DBConnectionPool.getDBConnection("MetaCatServlet.getPublicIdForDoc");
2625
      serialNumber=conn.getCheckOutSerialNumber();
2626
      pstmt = conn.prepareStatement(
2627
            "SELECT " + fieldName + " FROM xml_documents " +
2628
            "WHERE docid = ? ");
2629

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

    
2657
      }
2658
      finally
2659
      {
2660
        DBConnectionPool.returnDBConnection(conn, serialNumber);
2661
      }
2662
    }
2663
    return fieldValue;
2664
  }//getFieldValueForDoc
2665

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

    
2700
    // if no error and no success info, send a error that nothing happened
2701
    if( !error && !success)
2702
    {
2703
      out.println(ERROR);
2704
      out.println("Nothing happend for setaccess action");
2705
      out.println(ERRORCLOSE);
2706
    }
2707

    
2708
  }//outputResponse
2709
}
(39-39/56)