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-03-19 11:07:07 -0800 (Wed, 19 Mar 2003) $'
11
 * '$Revision: 1489 $'
12
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
 */
27

    
28
package edu.ucsb.nceas.metacat;
29

    
30
import com.oreilly.servlet.multipart.FilePart;
31
import com.oreilly.servlet.multipart.MultipartParser;
32
import com.oreilly.servlet.multipart.ParamPart;
33
import com.oreilly.servlet.multipart.Part;
34

    
35
import java.io.File;
36
import java.io.PrintWriter;
37
import java.io.IOException;
38
import java.io.StringReader;
39
import java.io.FileInputStream;
40
import java.io.BufferedInputStream;
41
import java.util.Enumeration;
42
import java.util.Hashtable;
43
import java.util.ResourceBundle;
44
import java.util.Random;
45
import java.util.PropertyResourceBundle;
46
import java.util.Vector;
47
import java.net.URL;
48
import java.net.MalformedURLException;
49
import java.sql.PreparedStatement;
50
import java.sql.ResultSet;
51
import java.sql.Connection;
52
import java.sql.SQLException;
53
import java.lang.reflect.*;
54
import java.net.*;
55
import java.util.zip.*;
56

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

    
68
import org.ecoinformatics.eml.EMLParser;
69

    
70
import org.xml.sax.SAXException;
71

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

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

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

    
140
      util = new MetaCatUtil();
141

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

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

    
154

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

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

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

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

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

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

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

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

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

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

    
216

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

    
223

    
224
      while (paramlist.hasMoreElements()) {
225

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

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

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

    
242

    
243
      //handle param is emptpy
244
      if (params.isEmpty() || params == null)
245
      {
246
        return;
247
      }
248
      //if the user clicked on the input images, decode which image
249
      //was clicked then set the action.
250
      String action = ((String[])params.get("action"))[0];
251
      util.debugMessage("Line 230: Action is: " + action, 1);
252

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

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

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

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

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

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

    
315
       // Now that we know the session is valid, we can delegate the request
316
      // to a particular action handler
317
      if(action.equals("query")) {
318
        PrintWriter out = response.getWriter();
319
        handleQuery(out,params,response,username,groupnames);
320
        out.close();
321
      } else if(action.equals("squery")) {
322
        PrintWriter out = response.getWriter();
323
        if(params.containsKey("query")) {
324
         handleSQuery(out, params,response,username,groupnames);
325
         out.close();
326
        } else {
327
          out.println("Illegal action squery without \"query\" parameter");
328
          out.close();
329
        }
330
      } else if (action.equals("export")) {
331

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

    
441
      //util.closeConnections();
442
      // Close the stream to the client
443
      //out.close();
444
    }
445
  }
446

    
447
  // LOGIN & LOGOUT SECTION
448
  /**
449
   * Handle the login request. Create a new session object.
450
   * Do user authentication through the session.
451
   */
452
  private void handleLoginAction(PrintWriter out, Hashtable params,
453
               HttpServletRequest request, HttpServletResponse response) {
454

    
455
    AuthSession sess = null;
456
    String un = ((String[])params.get("username"))[0];
457
    String pw = ((String[])params.get("password"))[0];
458
    String action = ((String[])params.get("action"))[0];
459
    String qformat = ((String[])params.get("qformat"))[0];
460

    
461
    try {
462
      sess = new AuthSession();
463
    } catch (Exception e) {
464
      System.out.println("error in MetacatServlet.handleLoginAction: " +
465
                          e.getMessage());
466
      out.println(e.getMessage());
467
      return;
468
    }
469
    boolean isValid = sess.authenticate(request, un, pw);
470
    // format and transform the output
471
    if (qformat.equals("xml")) {
472
      response.setContentType("text/xml");
473
      out.println(sess.getMessage());
474
    } else {
475

    
476
      try {
477

    
478
        DBTransform trans = new DBTransform();
479
        response.setContentType("text/html");
480
        trans.transformXMLDocument(sess.getMessage(), "-//NCEAS//login//EN",
481
                                   "-//W3C//HTML//EN", qformat, out);
482

    
483
      } catch(Exception e) {
484

    
485
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLoginAction: "
486
                                +e.getMessage(), 30);
487
      }
488

    
489
    // any output is returned
490
    }
491
  }
492

    
493
  /**
494
   * Handle the logout request. Close the connection.
495
   */
496
  private void handleLogoutAction(PrintWriter out, Hashtable params,
497
               HttpServletRequest request, HttpServletResponse response) {
498

    
499
    String qformat = ((String[])params.get("qformat"))[0];
500

    
501
    // close the connection
502
    HttpSession sess = request.getSession(false);
503
    if (sess != null) { sess.invalidate();  }
504

    
505
    // produce output
506
    StringBuffer output = new StringBuffer();
507
    output.append("<?xml version=\"1.0\"?>");
508
    output.append("<logout>");
509
    output.append("User logged out");
510
    output.append("</logout>");
511

    
512
    //format and transform the output
513
    if (qformat.equals("xml")) {
514
      response.setContentType("text/xml");
515
      out.println(output.toString());
516
    } else {
517

    
518
      try {
519

    
520
        DBTransform trans = new DBTransform();
521
        response.setContentType("text/html");
522
        trans.transformXMLDocument(output.toString(), "-//NCEAS//login//EN",
523
                                   "-//W3C//HTML//EN", qformat, out);
524

    
525
      } catch(Exception e) {
526

    
527
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLogoutAction"
528
                                  +e.getMessage(), 30);
529
      }
530
    }
531
  }
532
  // END OF LOGIN & LOGOUT SECTION
533

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

    
557
    resultdoc = createResultDocument(doclist, transformQuery(xmlquery));
558
    double toStringTime = System.currentTimeMillis()/1000;
559
    MetaCatUtil.debugMessage("Time to create xml string: "
560
                              +(toStringTime-docListTime), 30);
561
    //format and transform the results
562
    double outPutTime = 0;
563
    if(qformat.equals("xml")) {
564
      response.setContentType("text/xml");
565
      out.println(resultdoc);
566
      outPutTime = System.currentTimeMillis()/1000;
567
      MetaCatUtil.debugMessage("Output time: "+(outPutTime-toStringTime), 30);
568
    } else {
569
      transformResultset(resultdoc, response, out, qformat);
570
      outPutTime = System.currentTimeMillis()/1000;
571
      MetaCatUtil.debugMessage("Output time: "+(outPutTime-toStringTime), 30);
572
    }
573
  }
574

    
575
   /**
576
    * Create the xml query, execute it and display the results.
577
    *
578
    * @param out the output stream to the client
579
    * @param params the Hashtable of parameters that should be included
580
    * in the squery.
581
    * @param response the response object linked to the client
582
    */
583
  protected void handleQuery(PrintWriter out, Hashtable params,
584
                 HttpServletResponse response, String user, String[] groups)
585
  {
586
    //create the query and run it
587
    String xmlquery = DBQuery.createSQuery(params);
588
    Hashtable doclist = runQuery(xmlquery, user, groups);
589
    String qformat = ((String[])params.get("qformat"))[0];
590
    String resultdoc = null;
591

    
592
    resultdoc = createResultDocument(doclist, transformQuery(params));
593

    
594
    //format and transform the results
595
    if(qformat.equals("xml")) {
596
      response.setContentType("text/xml");
597
      out.println(resultdoc);
598
    } else {
599
      transformResultset(resultdoc, response, out, qformat);
600
    }
601
  }
602

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

    
623
  /**
624
   * removes the <?xml version="1.0"?> tag from the beginning.  This takes a
625
   * string as a param instead of a hashtable.
626
   *
627
   * @param xmlquery a string representing a query.
628
   */
629
  protected String transformQuery(String xmlquery)
630
  {
631
    xmlquery = xmlquery.trim();
632
    int index = xmlquery.indexOf("?>");
633
    return xmlquery.substring(index + 2, xmlquery.length());
634
  }
635

    
636
  /**
637
   * Run the query and return a hashtable of results.
638
   *
639
   * @param xmlquery the query to run
640
   */
641
  private Hashtable runQuery(String xmlquery, String user, String[] groups)
642
  {
643
    Hashtable doclist=null;
644

    
645
    try
646
    {
647

    
648
      DBQuery queryobj = new DBQuery(saxparser);
649
      doclist = queryobj.findDocuments(new StringReader(xmlquery),user,groups);
650

    
651
      return doclist;
652
    }
653
    catch (Exception e)
654
    {
655

    
656
      MetaCatUtil.debugMessage("Error in MetacatServlet.runQuery: "
657
                                                      + e.getMessage(), 30);
658
      doclist = null;
659
      return doclist;
660
    }
661
  }
662

    
663
  /**
664
   * Transorms an xml resultset document to html and sends it to the browser
665
   *
666
   * @param resultdoc the string representation of the document that needs
667
   * to be transformed.
668
   * @param response the HttpServletResponse object bound to the client.
669
   * @param out the output stream to the client
670
   * @param qformat the name of the style-set to use for transformations
671
   */
672
  protected void transformResultset(String resultdoc,
673
                                    HttpServletResponse response,
674
                                    PrintWriter out, String qformat)
675
  {
676

    
677
    try {
678

    
679
      DBTransform trans = new DBTransform();
680
      response.setContentType("text/html");
681
      trans.transformXMLDocument(resultdoc, "-//NCEAS//resultset//EN",
682
                                 "-//W3C//HTML//EN", qformat, out);
683

    
684
    }
685
    catch(Exception e)
686
    {
687

    
688
      MetaCatUtil.debugMessage("Error in MetaCatServlet.transformResultset:"
689
                                +e.getMessage(), 30);
690
    }
691
  }
692

    
693
  /**
694
   * Transforms a hashtable of documents to an xml or html result.
695
   *
696
   * @param doclist- the hashtable to transform
697
   * @param xmlquery- the query that returned the doclist result
698
   */
699
  protected String createResultDocument(Hashtable doclist, String xmlquery)
700
  {
701
    // Create a buffer to hold the xml result
702
    StringBuffer resultset = new StringBuffer();
703

    
704
    // Print the resulting root nodes
705
    String docid = null;
706
    String document = null;
707
    resultset.append("<?xml version=\"1.0\"?>\n");
708
    resultset.append("<resultset>\n");
709

    
710
    resultset.append("  <query>" + xmlquery + "</query>");
711

    
712
    if(doclist != null)
713
    {
714
      Enumeration doclistkeys = doclist.keys();
715
      while (doclistkeys.hasMoreElements())
716
      {
717
        docid = (String)doclistkeys.nextElement();
718
        document = (String)doclist.get(docid);
719
        resultset.append("  <document>" + document + "</document>");
720
      }
721
    }
722

    
723
    resultset.append("</resultset>");
724
    return resultset.toString();
725
  }
726
  // END OF SQUERY & QUERY SECTION
727

    
728
 //Exoport section
729
 /**
730
   * Handle the "export" request of data package from Metacat in zip format
731
   * @param params the Hashtable of HTTP request parameters
732
   * @param response the HTTP response object linked to the client
733
   * @param user the username sent the request
734
   * @param groups the user's groupnames
735
   */
736
  private void handleExportAction(Hashtable params,
737
    HttpServletResponse response, String user, String[] groups, String passWord)
738
  {
739
    // Output stream
740
    ServletOutputStream out = null;
741
    // Zip output stream
742
    ZipOutputStream zOut = null;
743
    DocumentImpl docImpls=null;
744
    DBQuery queryObj=null;
745

    
746
    String[] docs = new String[10];
747
    String docId = "";
748

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

    
783
    }//try
784
    catch (Exception e)
785
    {
786
      try
787
      {
788
        response.setContentType("text/xml"); //MIME type
789
        // Send error message back
790
        if (out != null)
791
        {
792
            PrintWriter pw = new PrintWriter(out);
793
            pw.println("<?xml version=\"1.0\"?>");
794
            pw.println("<error>");
795
            pw.println(e.getMessage());
796
            pw.println("</error>");
797
            // Close printwriter
798
            pw.close();
799
            // Close output stream
800
            out.close();
801
        }//if
802
        // Close zip output stream
803
        if ( zOut != null )
804
        {
805
          zOut.close();
806
        }//if
807
      }//try
808
      catch (IOException ioe)
809
      {
810
        MetaCatUtil.debugMessage("Problem with the servlet output " +
811
                           "in MetacatServlet.handleExportAction: " +
812
                           ioe.getMessage(), 30);
813
      }//catch
814

    
815
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleExportAction: " +
816
                         e.getMessage(), 30);
817
      e.printStackTrace(System.out);
818

    
819
    }//catch
820

    
821
  }//handleExportAction
822

    
823
  
824
   //read inline data section
825
 /**
826
   * In eml2 document, the xml can have inline data and data was stripped off 
827
   * and store in file system. This action can be used to read inline data only
828
   * @param params the Hashtable of HTTP request parameters
829
   * @param response the HTTP response object linked to the client
830
   * @param user the username sent the request
831
   * @param groups the user's groupnames
832
   */
833
  private void handleReadInlineDataAction(Hashtable params,
834
                                          HttpServletResponse response,
835
                                          String user, String passWord,
836
                                          String[] groups)
837
  {
838
    String[] docs = new String[10];
839
    String inlineDataId = null;
840
    String docId = "";
841
    ServletOutputStream out = null;
842

    
843
    try
844
    {
845
      // read the params
846
      if (params.containsKey("dataid"))
847
      {
848
        docs = (String[])params.get("dataid");
849
      }//if
850
      // Get the docid
851
      inlineDataId=docs[0];
852
      // Make sure the client specify docid
853
      if (inlineDataId == null || inlineDataId.equals(""))
854
      {
855
        // Get a printwriter
856
        PrintWriter pw = response.getWriter();
857
        // Send back message
858
        pw.println("<?xml version=\"1.0\"?>");
859
        pw.println("<error>");
860
        pw.println("You didn't specify requested docid");
861
        pw.println("</error>");
862
        // Close printwriter
863
        pw.close();
864
        return;
865
      }//if
866
      
867
      // check for permission
868
      docId = MetaCatUtil.getDocIdWithRevFromInlineDataID(inlineDataId);
869
      
870
      // Get output stream
871
      out = response.getOutputStream();
872
      // read the inline data from the file
873
      String inlinePath = MetaCatUtil.getOption("inlinedatafilepath");
874
      File lineData = new File(inlinePath, inlineDataId);
875
      FileInputStream input = new FileInputStream(lineData);
876
      byte [] buffer = new byte[4*1024];
877
      int bytes = input.read(buffer);
878
      while (bytes != -1)
879
      {
880
        out.write(buffer, 0, bytes);
881
        bytes = input.read(buffer);
882
      }
883
      out.close();
884

    
885
    }//try
886
    catch (Exception e)
887
    {
888
      try
889
      {
890
        // Send error message back
891
        if (out != null)
892
        {
893
            PrintWriter pw = new PrintWriter(out);
894
            pw.println("<?xml version=\"1.0\"?>");
895
            pw.println("<error>");
896
            pw.println(e.getMessage());
897
            pw.println("</error>");
898
            // Close printwriter
899
            pw.close();
900
            // Close output stream
901
            out.close();
902
        }//if
903
     }//try
904
     catch (IOException ioe)
905
     {
906
        MetaCatUtil.debugMessage("Problem with the servlet output " +
907
                           "in MetacatServlet.handleExportAction: " +
908
                           ioe.getMessage(), 30);
909
     }//catch
910

    
911
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleReadInlineDataAction: " 
912
                                + e.getMessage(), 30);
913
   
914
    }//catch
915

    
916
  }//handleReadInlineDataAction
917
  
918
  
919
  
920
  
921
  // READ SECTION
922
  /**
923
   * Handle the "read" request of metadata/data files from Metacat
924
   * or any files from Internet;
925
   * transformed metadata XML document into HTML presentation if requested;
926
   * zip files when more than one were requested.
927
   *
928
   * @param params the Hashtable of HTTP request parameters
929
   * @param response the HTTP response object linked to the client
930
   * @param user the username sent the request
931
   * @param groups the user's groupnames
932
   */
933
  private void handleReadAction(Hashtable params, HttpServletResponse response,
934
                                String user, String passWord, String[] groups)
935
  {
936
    ServletOutputStream out = null;
937
    ZipOutputStream zout = null;
938
    PrintWriter pw = null;
939
    boolean zip = false;
940
    boolean withInlineData = true;
941

    
942
    try {
943
      String[] docs = new String[0];
944
      String docid = "";
945
      String qformat = "";
946
      String abstrpath = null;
947

    
948
      // read the params
949
      if (params.containsKey("docid")) {
950
        docs = (String[])params.get("docid");
951
      }
952
      if (params.containsKey("qformat")) {
953
        qformat = ((String[])params.get("qformat"))[0];
954
      }
955
      // the param for only metadata (eml)
956
      if (params.containsKey("inlinedata"))
957
      {
958
        
959
        String inlineData = ((String[])params.get("inlinedata"))[0];
960
        if (inlineData.equalsIgnoreCase("false"))
961
        {
962
          withInlineData = false;
963
        }
964
      } 
965
      if (params.containsKey("abstractpath")) {
966
        abstrpath = ((String[])params.get("abstractpath"))[0];
967
        if ( !abstrpath.equals("") && (abstrpath != null) ) {
968
          viewAbstract(response, abstrpath, docs[0]);
969
          return;
970
        }
971
      }
972
      if ( (docs.length > 1) || qformat.equals("zip") ) {
973
        zip = true;
974
        out = response.getOutputStream();
975
        response.setContentType("application/zip"); //MIME type
976
        zout = new ZipOutputStream(out);
977
      }
978
      // go through the list of docs to read
979
      for (int i=0; i < docs.length; i++ ) {
980
        try {
981

    
982
          URL murl = new URL(docs[i]);
983
          Hashtable murlQueryStr = util.parseQuery(murl.getQuery());
984
          // case docid="http://.../?docid=aaa"
985
          // or docid="metacat://.../?docid=bbb"
986
          if (murlQueryStr.containsKey("docid")) {
987
            // get only docid, eliminate the rest
988
            docid = (String)murlQueryStr.get("docid");
989
            if ( zip ) {
990
              addDocToZip(docid, zout, user, groups);
991
            } else {
992
              readFromMetacat(response, docid, qformat, abstrpath,
993
                              user, groups, zip, zout, withInlineData);
994
            }
995

    
996
          // case docid="http://.../filename"
997
          } else {
998
            docid = docs[i];
999
            if ( zip ) {
1000
              addDocToZip(docid, zout, user, groups);
1001
            } else {
1002
              readFromURLConnection(response, docid);
1003
            }
1004
          }
1005

    
1006
        // case docid="ccc"
1007
        } catch (MalformedURLException mue) {
1008
          docid = docs[i];
1009
          if ( zip ) {
1010
            addDocToZip(docid, zout, user, groups);
1011
          } else {
1012
            readFromMetacat(response, docid, qformat, abstrpath,
1013
                            user, groups, zip, zout, withInlineData);
1014
          }
1015
        }
1016

    
1017
      } /* end for */
1018

    
1019
      if ( zip ) {
1020
        zout.finish(); //terminate the zip file
1021
        zout.close();  //close the zip stream
1022
      }
1023

    
1024

    
1025
    }
1026
    // To handle doc not found exception
1027
    catch (McdbDocNotFoundException notFoundE)
1028
    {
1029
      // the docid which didn't be found
1030
      String notFoundDocId = notFoundE.getUnfoundDocId();
1031
      String notFoundRevision = notFoundE.getUnfoundRevision();
1032
      MetaCatUtil.debugMessage("Missed id: "+ notFoundDocId, 30);
1033
      MetaCatUtil.debugMessage("Missed rev: "+ notFoundRevision, 30);
1034
      try
1035
      {
1036
        // read docid from remote server
1037
        readFromRemoteMetaCat(response, notFoundDocId, notFoundRevision,
1038
                                              user, passWord, out, zip, zout);
1039
        // Close zout outputstream
1040
        if ( zout != null)
1041
        {
1042
          zout.close();
1043
        }
1044
        // close output stream
1045
        if (out != null)
1046
        {
1047
          out.close();
1048
        }
1049

    
1050
      }//try
1051
      catch ( Exception exc)
1052
      {
1053
        MetaCatUtil.debugMessage("Erorr in MetacatServlet.hanldReadAction: "+
1054
                                      exc.getMessage(), 30);
1055
        try
1056
        {
1057
          if (out != null)
1058
          {
1059
            response.setContentType("text/xml");
1060
            // Send back error message by printWriter
1061
            pw = new PrintWriter(out);
1062
            pw.println("<?xml version=\"1.0\"?>");
1063
            pw.println("<error>");
1064
            pw.println(notFoundE.getMessage());
1065
            pw.println("</error>");
1066
            pw.close();
1067
            out.close();
1068

    
1069
          }
1070
          else
1071
          {
1072
           response.setContentType("text/xml"); //MIME type
1073
           // Send back error message if out = null
1074
           if (pw == null)
1075
           {
1076
             // If pw is null, open the respnose
1077
            pw = response.getWriter();
1078
           }
1079
           pw.println("<?xml version=\"1.0\"?>");
1080
           pw.println("<error>");
1081
           pw.println(notFoundE.getMessage());
1082
           pw.println("</error>");
1083
           pw.close();
1084
        }
1085
        // close zout
1086
        if ( zout != null )
1087
        {
1088
          zout.close();
1089
        }
1090
        }//try
1091
        catch (IOException ie)
1092
        {
1093
          MetaCatUtil.debugMessage("Problem with the servlet output " +
1094
                           "in MetacatServlet.handleReadAction: " +
1095
                           ie.getMessage(), 30);
1096
        }//cathch
1097
      }//catch
1098
    }// catch McdbDocNotFoundException
1099
    catch (Exception e)
1100
    {
1101
      try {
1102

    
1103
        if (out != null) {
1104
            response.setContentType("text/xml"); //MIME type
1105
            pw = new PrintWriter(out);
1106
            pw.println("<?xml version=\"1.0\"?>");
1107
            pw.println("<error>");
1108
            pw.println(e.getMessage());
1109
            pw.println("</error>");
1110
            pw.close();
1111
            out.close();
1112
        }
1113
        else
1114
        {
1115
           response.setContentType("text/xml"); //MIME type
1116
           // Send back error message if out = null
1117
           if ( pw == null)
1118
           {
1119
            pw = response.getWriter();
1120
           }
1121
           pw.println("<?xml version=\"1.0\"?>");
1122
           pw.println("<error>");
1123
           pw.println(e.getMessage());
1124
           pw.println("</error>");
1125
           pw.close();
1126

    
1127
        }
1128
        // Close zip output stream
1129
        if ( zout != null ) { zout.close(); }
1130

    
1131
      } catch (IOException ioe) {
1132
        MetaCatUtil.debugMessage("Problem with the servlet output " +
1133
                           "in MetacatServlet.handleReadAction: " +
1134
                           ioe.getMessage(), 30);
1135
        ioe.printStackTrace(System.out);
1136

    
1137
      }
1138

    
1139
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleReadAction: " +
1140
                               e.getMessage(), 30);
1141
      //e.printStackTrace(System.out);
1142
    }
1143

    
1144
  }
1145

    
1146
  // read metadata or data from Metacat
1147
  private void readFromMetacat(HttpServletResponse response, String docid,
1148
                               String qformat, String abstrpath, String user,
1149
                               String[] groups, boolean zip, 
1150
                               ZipOutputStream zout, boolean withInlineData)
1151
               throws ClassNotFoundException, IOException, SQLException,
1152
                      McdbException, Exception
1153
  {
1154

    
1155
    try {
1156

    
1157

    
1158
      DocumentImpl doc = new DocumentImpl(docid);
1159

    
1160
      //check the permission for read
1161
      if (!doc.hasReadPermission(user, groups, docid))
1162
      {
1163
        Exception e = new Exception("User " + user + " does not have permission"
1164
                       +" to read the document with the docid " + docid);
1165

    
1166
        throw e;
1167
      }
1168

    
1169
      if ( doc.getRootNodeID() == 0 ) {
1170
        // this is data file
1171
        String filepath = util.getOption("datafilepath");
1172
        if(!filepath.endsWith("/")) {
1173
          filepath += "/";
1174
        }
1175
        String filename = filepath + docid;
1176
        FileInputStream fin = null;
1177
        fin = new FileInputStream(filename);
1178

    
1179
        //MIME type
1180
        String contentType = getServletContext().getMimeType(filename);
1181
        if (contentType == null) {
1182
          if (filename.endsWith(".xml")) {
1183
            contentType="text/xml";
1184
          } else if (filename.endsWith(".css")) {
1185
            contentType="text/css";
1186
          } else if (filename.endsWith(".dtd")) {
1187
            contentType="text/plain";
1188
          } else if (filename.endsWith(".xsd")) {
1189
            contentType="text/xml";
1190
          } else if (filename.endsWith("/")) {
1191
            contentType="text/html";
1192
          } else {
1193
            File f = new File(filename);
1194
            if ( f.isDirectory() ) {
1195
              contentType="text/html";
1196
            } else {
1197
              // Use the content type set in the metacat.properties file
1198
              contentType= util.getOption("defaultcontenttype");
1199
              System.out.println(" default content type: "+ contentType);
1200
              if ( contentType == null ) {
1201
              contentType="application/octet-stream";
1202
              }
1203
            }
1204
          }
1205
        }
1206
        System.out.println("final content type: "+contentType);
1207
        response.setContentType(contentType);
1208
        // if we decide to use "application/octet-stream" for all data returns
1209
        // response.setContentType("application/octet-stream");
1210

    
1211
        try {
1212

    
1213
          ServletOutputStream out = response.getOutputStream();
1214
          byte[] buf = new byte[4 * 1024]; // 4K buffer
1215
          int b = fin.read(buf);
1216
          while (b != -1) {
1217
            out.write(buf, 0, b);
1218
            b = fin.read(buf);
1219
          }
1220
        } finally {
1221
          if (fin != null) fin.close();
1222
        }
1223

    
1224
      } else {
1225
        // this is metadata doc
1226
        if ( qformat.equals("xml") ) {
1227

    
1228
          // set content type first
1229
          response.setContentType("text/xml");   //MIME type
1230
          PrintWriter out = response.getWriter();
1231
          doc.toXml(out, user, groups, withInlineData);
1232
        } else {
1233
          response.setContentType("text/html");  //MIME type
1234
          PrintWriter out = response.getWriter();
1235

    
1236
          // Look up the document type
1237
          String doctype = doc.getDoctype();
1238
          // Transform the document to the new doctype
1239
          DBTransform dbt = new DBTransform();
1240
          dbt.transformXMLDocument(doc.toString(user, groups, withInlineData),
1241
                                   doctype,"-//W3C//HTML//EN", qformat, out);
1242
        }
1243

    
1244
      }
1245
    }
1246
    catch (Exception except)
1247
    {
1248
      throw except;
1249

    
1250
    }
1251

    
1252
  }
1253

    
1254
  // read data from URLConnection
1255
  private void readFromURLConnection(HttpServletResponse response, String docid)
1256
               throws IOException, MalformedURLException
1257
  {
1258
    ServletOutputStream out = response.getOutputStream();
1259
    String contentType = getServletContext().getMimeType(docid); //MIME type
1260
    if (contentType == null) {
1261
      if (docid.endsWith(".xml")) {
1262
        contentType="text/xml";
1263
      } else if (docid.endsWith(".css")) {
1264
        contentType="text/css";
1265
      } else if (docid.endsWith(".dtd")) {
1266
        contentType="text/plain";
1267
      } else if (docid.endsWith(".xsd")) {
1268
        contentType="text/xml";
1269
      } else if (docid.endsWith("/")) {
1270
        contentType="text/html";
1271
      } else {
1272
        File f = new File(docid);
1273
        if ( f.isDirectory() ) {
1274
          contentType="text/html";
1275
        } else {
1276
          contentType="application/octet-stream";
1277
        }
1278
      }
1279
    }
1280
    response.setContentType(contentType);
1281
    // if we decide to use "application/octet-stream" for all data returns
1282
    // response.setContentType("application/octet-stream");
1283

    
1284
    // this is http url
1285
    URL url = new URL(docid);
1286
    BufferedInputStream bis = null;
1287
    try {
1288
      bis = new BufferedInputStream(url.openStream());
1289
      byte[] buf = new byte[4 * 1024]; // 4K buffer
1290
      int b = bis.read(buf);
1291
      while (b != -1) {
1292
        out.write(buf, 0, b);
1293
        b = bis.read(buf);
1294
      }
1295
    } finally {
1296
      if (bis != null) bis.close();
1297
    }
1298

    
1299
  }
1300

    
1301
  // read file/doc and write to ZipOutputStream
1302
  private void addDocToZip(String docid, ZipOutputStream zout,
1303
                              String user, String[] groups)
1304
               throws ClassNotFoundException, IOException, SQLException,
1305
                      McdbException, Exception
1306
  {
1307
    byte[] bytestring = null;
1308
    ZipEntry zentry = null;
1309

    
1310
    try {
1311
      URL url = new URL(docid);
1312

    
1313
      // this http url; read from URLConnection; add to zip
1314
      zentry = new ZipEntry(docid);
1315
      zout.putNextEntry(zentry);
1316
      BufferedInputStream bis = null;
1317
      try {
1318
        bis = new BufferedInputStream(url.openStream());
1319
        byte[] buf = new byte[4 * 1024]; // 4K buffer
1320
        int b = bis.read(buf);
1321
        while(b != -1) {
1322
          zout.write(buf, 0, b);
1323
          b = bis.read(buf);
1324
        }
1325
      } finally {
1326
        if (bis != null) bis.close();
1327
      }
1328
      zout.closeEntry();
1329

    
1330
    } catch (MalformedURLException mue) {
1331

    
1332
      // this is metacat doc (data file or metadata doc)
1333

    
1334
      try {
1335

    
1336
        DocumentImpl doc = new DocumentImpl(docid);
1337

    
1338
        //check the permission for read
1339
        if (!doc.hasReadPermission(user, groups, docid))
1340
        {
1341
          Exception e = new Exception("User " + user + " does not have "
1342
                    +"permission to read the document with the docid " + docid);
1343

    
1344
          throw e;
1345
        }
1346

    
1347
        if ( doc.getRootNodeID() == 0 ) {
1348
          // this is data file; add file to zip
1349
          String filepath = util.getOption("datafilepath");
1350
          if(!filepath.endsWith("/")) {
1351
            filepath += "/";
1352
          }
1353
          String filename = filepath + docid;
1354
          FileInputStream fin = null;
1355
          fin = new FileInputStream(filename);
1356
          try {
1357

    
1358
            zentry = new ZipEntry(docid);
1359
            zout.putNextEntry(zentry);
1360
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1361
            int b = fin.read(buf);
1362
            while (b != -1) {
1363
              zout.write(buf, 0, b);
1364
              b = fin.read(buf);
1365
            }
1366
          } finally {
1367
            if (fin != null) fin.close();
1368
          }
1369
          zout.closeEntry();
1370

    
1371
        } else {
1372
          // this is metadata doc; add doc to zip
1373
          bytestring = doc.toString().getBytes();
1374
          zentry = new ZipEntry(docid + ".xml");
1375
          zentry.setSize(bytestring.length);
1376
          zout.putNextEntry(zentry);
1377
          zout.write(bytestring, 0, bytestring.length);
1378
          zout.closeEntry();
1379
        }
1380
      } catch (Exception except) {
1381
        throw except;
1382

    
1383
      }
1384

    
1385
    }
1386

    
1387
  }
1388

    
1389
  // view abstract within document
1390
  private void viewAbstract(HttpServletResponse response,
1391
                            String abstractpath, String docid)
1392
               throws ClassNotFoundException, IOException, SQLException,
1393
                      McdbException, Exception
1394
  {
1395

    
1396
    PrintWriter out =null;
1397
    try {
1398

    
1399
      response.setContentType("text/html");  //MIME type
1400
      out = response.getWriter();
1401
      Object[] abstracts = DBQuery.getNodeContent(abstractpath, docid);
1402
      out.println("<html><head><title>Abstract</title></head>");
1403
      out.println("<body bgcolor=\"white\"><h1>Abstract</h1>");
1404
      for (int i=0; i<abstracts.length; i++) {
1405
        out.println("<p>" + (String)abstracts[i] + "</p>");
1406
      }
1407
      out.println("</body></html>");
1408

    
1409
    } catch (Exception e) {
1410
       out.println("<?xml version=\"1.0\"?>");
1411
       out.println("<error>");
1412
       out.println(e.getMessage());
1413
       out.println("</error>");
1414

    
1415

    
1416
    }
1417
  }
1418
  /**
1419
   * If metacat couldn't find a data file or document locally, it will read this
1420
   * docid from its home server. This is for the replication feature
1421
   */
1422
  private void readFromRemoteMetaCat(HttpServletResponse response, String docid,
1423
                     String rev, String user, String password,
1424
                     ServletOutputStream out, boolean zip, ZipOutputStream zout)
1425
                        throws Exception
1426
 {
1427
   // Create a object of RemoteDocument, "" is for zipEntryPath
1428
   RemoteDocument remoteDoc =
1429
                        new RemoteDocument (docid, rev,user, password, "");
1430
   String docType = remoteDoc.getDocType();
1431
   // Only read data file
1432
   if (docType.equals("BIN"))
1433
   {
1434
    // If it is zip format
1435
    if (zip)
1436
    {
1437
      remoteDoc.readDocumentFromRemoteServerByZip(zout);
1438
    }//if
1439
    else
1440
    {
1441
      if (out == null)
1442
      {
1443
        out = response.getOutputStream();
1444
      }//if
1445
      response.setContentType("application/octet-stream");
1446
      remoteDoc.readDocumentFromRemoteServer(out);
1447
    }//else (not zip)
1448
   }//if doctype=bin
1449
   else
1450
   {
1451
     throw new Exception("Docid: "+docid+"."+rev+" couldn't find");
1452
   }//else
1453
 }//readFromRemoteMetaCat
1454

    
1455
  // END OF READ SECTION
1456
  
1457
 
1458
  
1459
  // INSERT/UPDATE SECTION
1460
  /**
1461
   * Handle the database putdocument request and write an XML document
1462
   * to the database connection
1463
   */
1464
  private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params,
1465
               String user, String[] groups) {
1466

    
1467
    DBConnection dbConn = null;
1468
    int serialNumber = -1;
1469

    
1470
    try {
1471
      // Get the document indicated
1472
      String[] doctext = (String[])params.get("doctext");
1473

    
1474
      String pub = null;
1475
      if (params.containsKey("public")) {
1476
        pub = ((String[])params.get("public"))[0];
1477
      }
1478

    
1479
      StringReader dtd = null;
1480
      if (params.containsKey("dtdtext")) {
1481
        String[] dtdtext = (String[])params.get("dtdtext");
1482
        try {
1483
          if ( !dtdtext[0].equals("") ) {
1484
            dtd = new StringReader(dtdtext[0]);
1485
          }
1486
        } catch (NullPointerException npe) {}
1487
      }
1488

    
1489
      StringReader xml = null;
1490
      boolean validate = false;
1491
      DocumentImplWrapper documentWrapper = null;
1492
      try {
1493
        // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1494
        // in order to decide whether to use validation parser
1495
        validate = needDTDValidation(doctext[0]);
1496
        if (validate)
1497
        {
1498
          // set a dtd base validation parser
1499
          String rule = DocumentImpl.DTD;
1500
          documentWrapper = new DocumentImplWrapper(rule, validate);
1501
        }
1502
        else if (needSchemaValidation(doctext[0]))
1503
        {
1504
          // for eml2
1505
          if (needEml2Validation(doctext[0]))
1506
          {
1507
             // set eml2 base validation parser
1508
            String rule = DocumentImpl.EML2;
1509
            // using emlparser to check id validation
1510
            EMLParser parser = new EMLParser(doctext[0]);
1511
            documentWrapper = new DocumentImplWrapper(rule, true);
1512
          }
1513
          else
1514
          {
1515
            // set schema base validation parser
1516
            String rule = DocumentImpl.SCHEMA;
1517
            documentWrapper = new DocumentImplWrapper(rule, true);
1518
          }
1519
        }
1520
        else
1521
        {
1522
          documentWrapper = new DocumentImplWrapper("", false);
1523
        }
1524
        
1525
        xml = new StringReader(doctext[0]);
1526

    
1527
        String[] action = (String[])params.get("action");
1528
        String[] docid = (String[])params.get("docid");
1529
        String newdocid = null;
1530

    
1531
        String doAction = null;
1532
        if (action[0].equals("insert")) {
1533
          doAction = "INSERT";
1534
        } else if (action[0].equals("update")) {
1535
          doAction = "UPDATE";
1536
        }
1537

    
1538
        try
1539
        {
1540
          // get a connection from the pool
1541
          dbConn=DBConnectionPool.
1542
                  getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1543
          serialNumber=dbConn.getCheckOutSerialNumber();
1544

    
1545

    
1546
          // write the document to the database
1547
          try
1548
          {
1549
            String accNumber = docid[0];
1550
            MetaCatUtil.debugMessage(""+ doAction + " " + accNumber +"...", 10);
1551
            if (accNumber.equals(""))
1552
            {
1553
              accNumber = null;
1554
            }//if
1555
            newdocid = documentWrapper.write(dbConn, xml, pub, dtd, doAction,
1556
                                          accNumber, user, groups);
1557

    
1558
          }//try
1559
          catch (NullPointerException npe)
1560
          {
1561
            newdocid = documentWrapper.write(dbConn, xml, pub, dtd, doAction,
1562
                                          null, user, groups);
1563
          }//catch
1564
        
1565
        }//try
1566
        finally
1567
        {
1568
          // Return db connection
1569
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1570
        }
1571

    
1572
        // set content type and other response header fields first
1573
        //response.setContentType("text/xml");
1574
        out.println("<?xml version=\"1.0\"?>");
1575
        out.println("<success>");
1576
        out.println("<docid>" + newdocid + "</docid>");
1577
        out.println("</success>");
1578

    
1579
      } 
1580
      catch (NullPointerException npe) 
1581
      {
1582
        //response.setContentType("text/xml");
1583
        out.println("<?xml version=\"1.0\"?>");
1584
        out.println("<error>");
1585
        out.println(npe.getMessage());
1586
        out.println("</error>");
1587
      }
1588
    } 
1589
    catch (Exception e) 
1590
    {
1591
      //response.setContentType("text/xml");
1592
      out.println("<?xml version=\"1.0\"?>");
1593
      out.println("<error>");
1594
      out.println(e.getMessage());
1595
      out.println("</error>");
1596
    }
1597
  }
1598

    
1599
  /**
1600
   * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1601
   * in order to decide whether to use validation parser
1602
   */
1603
  private static boolean needDTDValidation(String xmltext) throws IOException {
1604

    
1605
    StringReader xmlreader = new StringReader(xmltext);
1606
    StringBuffer cbuff = new StringBuffer();
1607
    java.util.Stack st = new java.util.Stack();
1608
    boolean validate = false;
1609
    int c;
1610
    int inx;
1611

    
1612
    // read from the stream until find the keywords
1613
    while ( (st.empty() || st.size()<4) && ((c = xmlreader.read()) != -1) ) {
1614
      cbuff.append((char)c);
1615

    
1616
      // "<!DOCTYPE" keyword is found; put it in the stack
1617
      if ( (inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1 ) {
1618
        cbuff = new StringBuffer();
1619
        st.push("<!DOCTYPE");
1620
      }
1621
      // "PUBLIC" keyword is found; put it in the stack
1622
      if ( (inx = cbuff.toString().indexOf("PUBLIC")) != -1 ) {
1623
        cbuff = new StringBuffer();
1624
        st.push("PUBLIC");
1625
      }
1626
      // "SYSTEM" keyword is found; put it in the stack
1627
      if ( (inx = cbuff.toString().indexOf("SYSTEM")) != -1 ) {
1628
        cbuff = new StringBuffer();
1629
        st.push("SYSTEM");
1630
      }
1631
      // ">" character is found; put it in the stack
1632
      // ">" is found twice: fisrt from <?xml ...?>
1633
      // and second from <!DOCTYPE ... >
1634
      if ( (inx = cbuff.toString().indexOf(">")) != -1 ) {
1635
        cbuff = new StringBuffer();
1636
        st.push(">");
1637
      }
1638
    }
1639

    
1640
    // close the stream
1641
    xmlreader.close();
1642

    
1643
    // check the stack whether it contains the keywords:
1644
    // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1645
    if ( st.size() == 4 ) {
1646
      if ( ((String)st.pop()).equals(">") &&
1647
           ( ((String)st.peek()).equals("PUBLIC") |
1648
             ((String)st.pop()).equals("SYSTEM") ) &&
1649
           ((String)st.pop()).equals("<!DOCTYPE") )  {
1650
        validate = true;
1651
      }
1652
    }
1653

    
1654
    MetaCatUtil.debugMessage("Validation for dtd is " + validate, 10);
1655
    return validate;
1656
  }
1657
  // END OF INSERT/UPDATE SECTION
1658
  
1659
  /* check if the xml string contains key words to specify schema loocation*/
1660
  private boolean needSchemaValidation(String xml)
1661
  {
1662
    boolean needSchemaValidate =false;
1663
    if (xml == null)
1664
    {
1665
      MetaCatUtil.debugMessage("Validation for schema is " +
1666
                               needSchemaValidate, 10);
1667
      return needSchemaValidate;
1668
    }
1669
    else if (xml.indexOf(SCHEMALOCATIONKEYWORD) != -1 ||
1670
             xml.indexOf(NONAMESPACELOCATION) != -1 )
1671
    {
1672
      // if contains schema location key word, should be validate
1673
      needSchemaValidate = true;
1674
    }
1675
    
1676
    MetaCatUtil.debugMessage("Validation for schema is " + 
1677
                             needSchemaValidate, 10);
1678
    return needSchemaValidate;
1679
   
1680
  }
1681
  
1682
   /* check if the xml string contains key words to specify schema loocation*/
1683
  private boolean needEml2Validation(String xml)
1684
  {
1685
    boolean needEml2Validate =false;
1686
    if (xml == null)
1687
    {
1688
      MetaCatUtil.debugMessage("Validation for schema is " +
1689
                               needEml2Validate, 10);
1690
      return needEml2Validate;
1691
    }
1692
    else if (xml.indexOf(EML2KEYWORD) != -1)
1693
    {
1694
      // if contains schema location key word, should be validate
1695
      needEml2Validate = true;
1696
    }
1697
    
1698
    MetaCatUtil.debugMessage("Validation for eml is " + 
1699
                             needEml2Validate, 10);
1700
    return needEml2Validate;
1701
   
1702
  }
1703
  
1704
  // DELETE SECTION
1705
  /**
1706
   * Handle the database delete request and delete an XML document
1707
   * from the database connection
1708
   */
1709
  private void handleDeleteAction(PrintWriter out, Hashtable params,
1710
               HttpServletResponse response, String user, String[] groups) {
1711

    
1712
    String[] docid = (String[])params.get("docid");
1713

    
1714
    // delete the document from the database
1715
    try {
1716

    
1717
                                      // NOTE -- NEED TO TEST HERE
1718
                                      // FOR EXISTENCE OF DOCID PARAM
1719
                                      // BEFORE ACCESSING ARRAY
1720
      try {
1721
        DocumentImpl.delete(docid[0], user, groups);
1722
        response.setContentType("text/xml");
1723
        out.println("<?xml version=\"1.0\"?>");
1724
        out.println("<success>");
1725
        out.println("Document deleted.");
1726
        out.println("</success>");
1727
      } catch (AccessionNumberException ane) {
1728
        response.setContentType("text/xml");
1729
        out.println("<?xml version=\"1.0\"?>");
1730
        out.println("<error>");
1731
        out.println("Error deleting document!!!");
1732
        out.println(ane.getMessage());
1733
        out.println("</error>");
1734
      }
1735
    } catch (Exception e) {
1736
      response.setContentType("text/xml");
1737
      out.println("<?xml version=\"1.0\"?>");
1738
      out.println("<error>");
1739
      out.println(e.getMessage());
1740
      out.println("</error>");
1741
    }
1742
  }
1743
  // END OF DELETE SECTION
1744

    
1745
  // VALIDATE SECTION
1746
  /**
1747
   * Handle the validation request and return the results to the requestor
1748
   */
1749
  private void handleValidateAction(PrintWriter out, Hashtable params) {
1750

    
1751
    // Get the document indicated
1752
    String valtext = null;
1753
    DBConnection dbConn = null;
1754
    int serialNumber = -1;
1755

    
1756
    try {
1757
      valtext = ((String[])params.get("valtext"))[0];
1758
    } catch (Exception nullpe) {
1759

    
1760

    
1761
      String docid = null;
1762
      try {
1763
        // Find the document id number
1764
        docid = ((String[])params.get("docid"))[0];
1765

    
1766

    
1767
        // Get the document indicated from the db
1768
        DocumentImpl xmldoc = new DocumentImpl(docid);
1769
        valtext = xmldoc.toString();
1770

    
1771
      } catch (NullPointerException npe) {
1772

    
1773
        out.println("<error>Error getting document ID: " + docid + "</error>");
1774
        //if ( conn != null ) { util.returnConnection(conn); }
1775
        return;
1776
      } catch (Exception e) {
1777

    
1778
        out.println(e.getMessage());
1779
      }
1780
    }
1781

    
1782

    
1783
    try {
1784
      // get a connection from the pool
1785
      dbConn=DBConnectionPool.
1786
                  getDBConnection("MetaCatServlet.handleValidateAction");
1787
      serialNumber=dbConn.getCheckOutSerialNumber();
1788
      DBValidate valobj = new DBValidate(saxparser,dbConn);
1789
      boolean valid = valobj.validateString(valtext);
1790

    
1791
      // set content type and other response header fields first
1792

    
1793
      out.println(valobj.returnErrors());
1794

    
1795
    } catch (NullPointerException npe2) {
1796
      // set content type and other response header fields first
1797

    
1798
      out.println("<error>Error validating document.</error>");
1799
    } catch (Exception e) {
1800

    
1801
      out.println(e.getMessage());
1802
    } finally {
1803
      // Return db connection
1804
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1805
    }
1806
  }
1807
  // END OF VALIDATE SECTION
1808

    
1809
  // OTHER ACTION HANDLERS
1810

    
1811
  /**
1812
   * Handle "getrevsionanddoctype" action
1813
   * Given a docid, return it's current revision and doctype from data base
1814
   * The output is String look like "rev;doctype"
1815
   */
1816
  private void handleGetRevisionAndDocTypeAction(PrintWriter out,
1817
                                                              Hashtable params)
1818
  {
1819
    // To store doc parameter
1820
    String [] docs = new String[10];
1821
    // Store a single doc id
1822
    String givenDocId = null;
1823
    // Get docid from parameters
1824
    if (params.containsKey("docid"))
1825
    {
1826
      docs = (String[])params.get("docid");
1827
    }
1828
    // Get first docid form string array
1829
    givenDocId = docs[0];
1830

    
1831
    try
1832
    {
1833
      // Make sure there is a docid
1834
      if (givenDocId == null || givenDocId.equals(""))
1835
      {
1836
        throw new Exception("User didn't specify docid!");
1837
      }//if
1838

    
1839
      // Create a DBUtil object
1840
      DBUtil dbutil = new DBUtil();
1841
      // Get a rev and doctype
1842
      String revAndDocType =
1843
                dbutil.getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
1844
      out.println(revAndDocType);
1845

    
1846
    }//try
1847
    catch (Exception e)
1848
    {
1849
      // Handle exception
1850
      out.println("<?xml version=\"1.0\"?>");
1851
      out.println("<error>");
1852
      out.println(e.getMessage());
1853
      out.println("</error>");
1854
    }//catch
1855

    
1856
  }//handleGetRevisionAndDocTypeAction
1857

    
1858
  /**
1859
   * Handle "getaccesscontrol" action.
1860
   * Read Access Control List from db connection in XML format
1861
   */
1862
  private void handleGetAccessControlAction(PrintWriter out, Hashtable params,
1863
                                       HttpServletResponse response,
1864
                                       String username, String[] groupnames) {
1865

    
1866
    DBConnection dbConn = null;
1867
    int serialNumber = -1;
1868
    String docid = ((String[])params.get("docid"))[0];
1869

    
1870
    try {
1871

    
1872
        // get connection from the pool
1873
        dbConn=DBConnectionPool.
1874
                 getDBConnection("MetaCatServlet.handleGetAccessControlAction");
1875
        serialNumber=dbConn.getCheckOutSerialNumber();
1876
        AccessControlList aclobj = new AccessControlList(dbConn);
1877
        String acltext = aclobj.getACL(docid, username, groupnames);
1878
        out.println(acltext);
1879

    
1880
    } catch (Exception e) {
1881
      out.println("<?xml version=\"1.0\"?>");
1882
      out.println("<error>");
1883
      out.println(e.getMessage());
1884
      out.println("</error>");
1885
    } finally {
1886
      // Retrun db connection to pool
1887
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1888
    }
1889

    
1890
  }
1891

    
1892
  /**
1893
   * Handle the "getprincipals" action.
1894
   * Read all principals from authentication scheme in XML format
1895
   */
1896
  private void handleGetPrincipalsAction(PrintWriter out, String user,
1897
                                         String password) {
1898

    
1899

    
1900
    try {
1901

    
1902

    
1903
        AuthSession auth = new AuthSession();
1904
        String principals = auth.getPrincipals(user, password);
1905
        out.println(principals);
1906

    
1907
    } catch (Exception e) {
1908
      out.println("<?xml version=\"1.0\"?>");
1909
      out.println("<error>");
1910
      out.println(e.getMessage());
1911
      out.println("</error>");
1912
    }
1913

    
1914
  }
1915

    
1916
  /**
1917
   * Handle "getdoctypes" action.
1918
   * Read all doctypes from db connection in XML format
1919
   */
1920
  private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
1921
                                       HttpServletResponse response) {
1922

    
1923

    
1924
    try {
1925

    
1926

    
1927
        DBUtil dbutil = new DBUtil();
1928
        String doctypes = dbutil.readDoctypes();
1929
        out.println(doctypes);
1930

    
1931
    } catch (Exception e) {
1932
      out.println("<?xml version=\"1.0\"?>");
1933
      out.println("<error>");
1934
      out.println(e.getMessage());
1935
      out.println("</error>");
1936
    }
1937

    
1938
  }
1939

    
1940
  /**
1941
   * Handle the "getdtdschema" action.
1942
   * Read DTD or Schema file for a given doctype from Metacat catalog system
1943
   */
1944
  private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
1945
                                        HttpServletResponse response) {
1946

    
1947

    
1948
    String doctype = null;
1949
    String[] doctypeArr = (String[])params.get("doctype");
1950

    
1951
    // get only the first doctype specified in the list of doctypes
1952
    // it could be done for all doctypes in that list
1953
    if (doctypeArr != null) {
1954
        doctype = ((String[])params.get("doctype"))[0];
1955
    }
1956

    
1957
    try {
1958

    
1959

    
1960
        DBUtil dbutil = new DBUtil();
1961
        String dtdschema = dbutil.readDTDSchema(doctype);
1962
        out.println(dtdschema);
1963

    
1964
    } catch (Exception e) {
1965
      out.println("<?xml version=\"1.0\"?>");
1966
      out.println("<error>");
1967
      out.println(e.getMessage());
1968
      out.println("</error>");
1969
    }
1970

    
1971
  }
1972

    
1973
  /**
1974
   * Handle the "getdataguide" action.
1975
   * Read Data Guide for a given doctype from db connection in XML format
1976
   */
1977
  private void handleGetDataGuideAction(PrintWriter out, Hashtable params,
1978
                                        HttpServletResponse response) {
1979

    
1980

    
1981
    String doctype = null;
1982
    String[] doctypeArr = (String[])params.get("doctype");
1983

    
1984
    // get only the first doctype specified in the list of doctypes
1985
    // it could be done for all doctypes in that list
1986
    if (doctypeArr != null) {
1987
        doctype = ((String[])params.get("doctype"))[0];
1988
    }
1989

    
1990
    try {
1991

    
1992

    
1993
        DBUtil dbutil = new DBUtil();
1994
        String dataguide = dbutil.readDataGuide(doctype);
1995
        out.println(dataguide);
1996

    
1997
    } catch (Exception e) {
1998
      out.println("<?xml version=\"1.0\"?>");
1999
      out.println("<error>");
2000
      out.println(e.getMessage());
2001
      out.println("</error>");
2002
    }
2003

    
2004
  }
2005

    
2006
  /**
2007
   * Handle the "getlastdocid" action.
2008
   * Get the latest docid with rev number from db connection in XML format
2009
   */
2010
  private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
2011
                                        HttpServletResponse response) {
2012

    
2013

    
2014
    String scope = ((String[])params.get("scope"))[0];
2015
    if (scope == null) {
2016
        scope = ((String[])params.get("username"))[0];
2017
    }
2018

    
2019
    try {
2020

    
2021

    
2022
        DBUtil dbutil = new DBUtil();
2023
        String lastDocid = dbutil.getMaxDocid(scope);
2024
        out.println("<?xml version=\"1.0\"?>");
2025
        out.println("<lastDocid>");
2026
        out.println("  <scope>" + scope + "</scope>");
2027
        out.println("  <docid>" + lastDocid + "</docid>");
2028
        out.println("</lastDocid>");
2029

    
2030
    } catch (Exception e) {
2031
      out.println("<?xml version=\"1.0\"?>");
2032
      out.println("<error>");
2033
      out.println(e.getMessage());
2034
      out.println("</error>");
2035
    }
2036

    
2037
  }
2038

    
2039
  /**
2040
   * Handle documents passed to metacat that are encoded using the
2041
   * "multipart/form-data" mime type.  This is typically used for uploading
2042
   * data files which may be binary and large.
2043
   */
2044
  private void handleMultipartForm(HttpServletRequest request,
2045
                                   HttpServletResponse response)
2046
  {
2047
    PrintWriter out = null;
2048
    String action = null;
2049

    
2050
    // Parse the multipart form, and save the parameters in a Hashtable and
2051
    // save the FileParts in a hashtable
2052

    
2053
    Hashtable params = new Hashtable();
2054
    Hashtable fileList = new Hashtable();
2055

    
2056
    try {
2057
      // MBJ: need to put filesize limit in Metacat config (metacat.properties)
2058
      MultipartParser mp = new MultipartParser(request, 200*1024*1024); //200MB
2059
      Part part;
2060
      while ((part = mp.readNextPart()) != null) {
2061
        String name = part.getName();
2062

    
2063
        if (part.isParam()) {
2064
          // it's a parameter part
2065
          ParamPart paramPart = (ParamPart) part;
2066
          String value = paramPart.getStringValue();
2067
          params.put(name, value);
2068
          if (name.equals("action")) {
2069
            action = value;
2070
          }
2071
        } else if (part.isFile()) {
2072
          // it's a file part
2073
          FilePart filePart = (FilePart) part;
2074
          fileList.put(name, filePart);
2075

    
2076
          // Stop once the first file part is found, otherwise going onto the
2077
          // next part prevents access to the file contents.  So...for upload
2078
          // to work, the datafile must be the last part
2079
          break;
2080
        }
2081
      }
2082
    } catch (IOException ioe) {
2083
      try {
2084
        out = response.getWriter();
2085
      } catch (IOException ioe2) {
2086
        System.err.println("Fatal Error: couldn't get response output stream.");
2087
      }
2088
      out.println("<?xml version=\"1.0\"?>");
2089
      out.println("<error>");
2090
      out.println("Error: problem reading multipart data.");
2091
      out.println("</error>");
2092
    }
2093

    
2094
    // Get the session information
2095
    String username = null;
2096
    String password = null;
2097
    String[] groupnames = null;
2098
    String sess_id = null;
2099

    
2100
    // be aware of session expiration on every request
2101
    HttpSession sess = request.getSession(true);
2102
    if (sess.isNew()) {
2103
      // session expired or has not been stored b/w user requests
2104
      username = "public";
2105
      sess.setAttribute("username", username);
2106
    } else {
2107
      username = (String)sess.getAttribute("username");
2108
      password = (String)sess.getAttribute("password");
2109
      groupnames = (String[])sess.getAttribute("groupnames");
2110
      try {
2111
        sess_id = (String)sess.getId();
2112
      } catch(IllegalStateException ise) {
2113
        System.out.println("error in  handleMultipartForm: this shouldn't " +
2114
                           "happen: the session should be valid: " +
2115
                           ise.getMessage());
2116
      }
2117
    }
2118

    
2119
    // Get the out stream
2120
    try {
2121
          out = response.getWriter();
2122
        } catch (IOException ioe2) {
2123
          util.debugMessage("Fatal Error: couldn't get response "+
2124
                                                              "output stream.");
2125
        }
2126

    
2127
    if ( action.equals("upload")) {
2128
      if (username != null &&  !username.equals("public")) {
2129
        handleUploadAction(request, out, params, fileList,
2130
                           username, groupnames);
2131
      } else {
2132

    
2133
        out.println("<?xml version=\"1.0\"?>");
2134
        out.println("<error>");
2135
        out.println("Permission denied for " + action);
2136
        out.println("</error>");
2137
      }
2138
    } else {
2139
      /*try {
2140
        out = response.getWriter();
2141
      } catch (IOException ioe2) {
2142
        System.err.println("Fatal Error: couldn't get response output stream.");
2143
      }*/
2144
      out.println("<?xml version=\"1.0\"?>");
2145
      out.println("<error>");
2146
      out.println("Error: action not registered.  Please report this error.");
2147
      out.println("</error>");
2148
    }
2149
    out.close();
2150
  }
2151

    
2152
  /**
2153
   * Handle the upload action by saving the attached file to disk and
2154
   * registering it in the Metacat db
2155
   */
2156
  private void handleUploadAction(HttpServletRequest request,
2157
                                  PrintWriter out,
2158
                                  Hashtable params, Hashtable fileList,
2159
                                  String username, String[] groupnames)
2160
  {
2161
    //PrintWriter out = null;
2162
    //Connection conn = null;
2163
    String action = null;
2164
    String docid = null;
2165

    
2166
    /*response.setContentType("text/xml");
2167
    try
2168
    {
2169
      out = response.getWriter();
2170
    }
2171
    catch (IOException ioe2)
2172
    {
2173
      System.err.println("Fatal Error: couldn't get response output stream.");
2174
    }*/
2175

    
2176
    if (params.containsKey("docid"))
2177
    {
2178
      docid = (String)params.get("docid");
2179
    }
2180

    
2181
    // Make sure we have a docid and datafile
2182
    if (docid != null && fileList.containsKey("datafile")) {
2183

    
2184
      // Get a reference to the file part of the form
2185
      FilePart filePart = (FilePart)fileList.get("datafile");
2186
      String fileName = filePart.getFileName();
2187
      MetaCatUtil.debugMessage("Uploading filename: " + fileName, 10);
2188

    
2189
      // Check if the right file existed in the uploaded data
2190
      if (fileName != null) {
2191

    
2192
        try
2193
        {
2194
           //MetaCatUtil.debugMessage("Upload datafile " + docid +"...", 10);
2195
           //If document get lock data file grant
2196
           if (DocumentImpl.getDataFileLockGrant(docid))
2197
           {
2198
              // register the file in the database (which generates an exception
2199
              //if the docid is not acceptable or other untoward things happen
2200
              DocumentImpl.registerDocument(fileName, "BIN", docid, username);
2201

    
2202
              // Save the data file to disk using "docid" as the name
2203
              dataDirectory.mkdirs();
2204
              File newFile = new File(dataDirectory, docid);
2205
              long size = filePart.writeTo(newFile);
2206

    
2207
              // Force replication this data file
2208
              // To data file, "insert" and update is same
2209
              // The fourth parameter is null. Because it is notification server
2210
              // and this method is in MetaCatServerlet. It is original command,
2211
              // not get force replication info from another metacat
2212
              ForceReplicationHandler frh = new ForceReplicationHandler
2213
                                                (docid, "insert", false, null);
2214

    
2215
              // set content type and other response header fields first
2216
              out.println("<?xml version=\"1.0\"?>");
2217
              out.println("<success>");
2218
              out.println("<docid>" + docid + "</docid>");
2219
              out.println("<size>" + size + "</size>");
2220
              out.println("</success>");
2221
          }//if
2222

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

    
2232
      }
2233
      else
2234
      {
2235
        // the field did not contain a file
2236
        out.println("<?xml version=\"1.0\"?>");
2237
        out.println("<error>");
2238
        out.println("The uploaded data did not contain a valid file.");
2239
        out.println("</error>");
2240
      }
2241
    }
2242
    else
2243
    {
2244
      // Error bcse docid missing or file missing
2245
      out.println("<?xml version=\"1.0\"?>");
2246
      out.println("<error>");
2247
      out.println("The uploaded data did not contain a valid docid " +
2248
                  "or valid file.");
2249
      out.println("</error>");
2250
    }
2251
  }
2252
  
2253
  /*
2254
   * A method to handle set access action
2255
   */
2256
  private void handleSetAccessAction(PrintWriter out,
2257
                                   Hashtable params,
2258
                                   String username)
2259
  {
2260
    String [] docList        = null;
2261
    String [] principalList  = null;
2262
    String [] permissionList = null;
2263
    String [] permTypeList   = null;
2264
    String [] permOrderList  = null;
2265
    String permission = null;
2266
    String permType   = null;
2267
    String permOrder  = null;
2268
    Vector errorList  = new Vector();
2269
    String error      = null;
2270
    Vector successList = new Vector();
2271
    String success    = null;
2272
   
2273
    
2274
    // Get parameters
2275
    if (params.containsKey("docid")) 
2276
    {
2277
      docList = (String[])params.get("docid");
2278
    }
2279
    if (params.containsKey("principal"))
2280
    {
2281
      principalList = (String[])params.get("principal"); 
2282
    }
2283
    if (params.containsKey("permission"))
2284
    {
2285
      permissionList = (String[])params.get("permission");
2286
      
2287
    }
2288
    if (params.containsKey("permType"))
2289
    {
2290
      permTypeList = (String[])params.get("permType");
2291
    
2292
    }
2293
    if (params.containsKey("permOrder"))
2294
    {
2295
      permOrderList = (String[])params.get("permOrder");
2296
     
2297
    }
2298
   
2299
    // Make sure the parameter is not null
2300
    if (docList == null || principalList == null || permTypeList == null ||
2301
        permissionList == null)
2302
    {
2303
      error = "Please check your parameter list, it should look like: "+
2304
              "?action=setaccess&docid=pipeline.1.1&principal=public" +
2305
              "&permission=read&permType=allow&permOrder=allowFirst";
2306
      errorList.addElement(error);
2307
      outputResponse(successList, errorList, out);
2308
      return;
2309
    }
2310
    
2311
    // Only select first element for permission, type and order
2312
    permission = permissionList[0];
2313
    permType = permTypeList[0];
2314
    if (permOrderList != null)
2315
    {
2316
       permOrder = permOrderList[0];
2317
    }
2318
    
2319
    // Get package doctype set
2320
    Vector packageSet =MetaCatUtil.getOptionList(
2321
                                    MetaCatUtil.getOption("packagedoctypeset"));
2322
    //debug
2323
    if (packageSet != null)
2324
    {
2325
      for (int i = 0; i<packageSet.size(); i++)
2326
      {
2327
        MetaCatUtil.debugMessage("doctype in package set: " + 
2328
                              (String)packageSet.elementAt(i), 34);
2329
      }
2330
    }//if
2331
    
2332
    // handle every accessionNumber
2333
    for (int i=0; i <docList.length; i++)
2334
    {
2335
      String accessionNumber = docList[i];
2336
      String owner = null;
2337
      String publicId = null;
2338
      // Get document owner and public id
2339
      try
2340
      {
2341
        owner = getFieldValueForDoc(accessionNumber, "user_owner");
2342
        publicId = getFieldValueForDoc(accessionNumber, "doctype");
2343
      }//try
2344
      catch (Exception e)
2345
      {
2346
        MetaCatUtil.debugMessage("Error in handleSetAccessAction: " +
2347
                                  e.getMessage(), 30);
2348
        error = "Error in set access control for document - " + accessionNumber+
2349
                 e.getMessage();
2350
        errorList.addElement(error);
2351
        continue;
2352
      }
2353
      //check if user is the owner. Only owner can do owner                            
2354
      if (username == null || owner == null || !username.equals(owner))
2355
      {
2356
        error = "User - " + username + " does not have permission to set " +
2357
                "access control for docid - " + accessionNumber;
2358
        errorList.addElement(error);
2359
        continue;
2360
      }
2361
      
2362
      // If docid publicid is BIN data file or other beta4, 6 package document
2363
      // we could not do set access control. Because we don't want inconsistent
2364
      // to its access docuemnt
2365
      if (publicId!=null && packageSet!=null && packageSet.contains(publicId))
2366
      {
2367
        error = "Could not set access control to document "+ accessionNumber +
2368
                "because it is in a pakcage and it has a access file for it";
2369
        errorList.addElement(error);
2370
        continue;
2371
      }
2372
      
2373
      // for every principle
2374
      for (int j = 0; j<principalList.length; j++)
2375
      {
2376
        String principal = principalList[j];
2377
        try
2378
        {
2379
          //insert permission
2380
          AccessControlForSingleFile accessControl = new 
2381
                           AccessControlForSingleFile(accessionNumber,
2382
                                    principal, permission, permType, permOrder);
2383
          accessControl.insertPermissions();
2384
          success = "Set access control to document "+ accessionNumber +
2385
                    " successfully";
2386
          successList.addElement(success);
2387
        }
2388
        catch (Exception ee)
2389
        {
2390
          MetaCatUtil.debugMessage("Erorr in handleSetAccessAction2: " +
2391
                                   ee.getMessage(), 30);
2392
          error = "Faild to set access control for document " + 
2393
                  accessionNumber + " because " + ee.getMessage();
2394
          errorList.addElement(error);
2395
          continue;
2396
        }
2397
      }//for every principle
2398
    }//for every document 
2399
    outputResponse(successList, errorList, out);
2400
  }//handleSetAccessAction
2401
  
2402
 
2403
  /*
2404
   * A method try to determin a docid's public id, if couldn't find null
2405
   * will be returned.
2406
   */
2407
  private String getFieldValueForDoc(String accessionNumber, String fieldName) 
2408
                                      throws Exception
2409
  {
2410
    if (accessionNumber==null || accessionNumber.equals("") ||fieldName == null
2411
        || fieldName.equals(""))
2412
    {
2413
      throw new Exception("Docid or field name was not specified");
2414
    }
2415
    
2416
    PreparedStatement pstmt = null;
2417
    ResultSet rs = null;
2418
    String fieldValue = null;
2419
    String docId = null;
2420
    DBConnection conn = null;
2421
    int serialNumber = -1;
2422
    
2423
    // get rid of revision if access number has
2424
    docId = MetaCatUtil.getDocIdFromString(accessionNumber);
2425
    try
2426
    {
2427
      //check out DBConnection
2428
      conn=DBConnectionPool.getDBConnection("MetaCatServlet.getPublicIdForDoc");
2429
      serialNumber=conn.getCheckOutSerialNumber();
2430
      pstmt = conn.prepareStatement(
2431
            "SELECT " + fieldName + " FROM xml_documents " +
2432
            "WHERE docid = ? ");
2433
          
2434
      pstmt.setString(1, docId);
2435
      pstmt.execute();
2436
      rs = pstmt.getResultSet();
2437
      boolean hasRow = rs.next();
2438
      int perm = 0;
2439
      if ( hasRow ) 
2440
      {
2441
        fieldValue = rs.getString(1);
2442
      }
2443
      else
2444
      {
2445
        throw new Exception("Could not find document: "+accessionNumber);
2446
      }
2447
    }//try
2448
    catch (Exception e)
2449
    {
2450
      MetaCatUtil.debugMessage("Exception in MetacatServlet.getPublicIdForDoc: "
2451
                               + e.getMessage(), 30);
2452
      throw e;
2453
    }
2454
    finally
2455
    {
2456
      try
2457
      {
2458
        rs.close();
2459
        pstmt.close();
2460
        
2461
      }
2462
      finally
2463
      {
2464
        DBConnectionPool.returnDBConnection(conn, serialNumber);
2465
      }
2466
    }
2467
    return fieldValue;
2468
  }//getFieldValueForDoc
2469
  
2470
  /*
2471
   * A method to output setAccess action result
2472
   */
2473
  private void outputResponse(Vector successList, 
2474
                              Vector errorList,
2475
                              PrintWriter out)
2476
  {
2477
    boolean error = false;
2478
    boolean success = false;
2479
    // Output prolog
2480
    out.println(PROLOG);
2481
    // output success message
2482
    if ( successList != null)
2483
    {
2484
      for (int i = 0; i<successList.size(); i++)
2485
      {
2486
        out.println(SUCCESS);
2487
        out.println((String)successList.elementAt(i));
2488
        out.println(SUCCESSCLOSE);
2489
        success = true;
2490
      }//for
2491
    }//if
2492
    // output error message
2493
    if (errorList != null)
2494
    {
2495
      for (int i = 0; i<errorList.size(); i++)
2496
      {
2497
        out.println(ERROR);
2498
        out.println((String)errorList.elementAt(i));
2499
        out.println(ERRORCLOSE);
2500
        error = true;
2501
      }//for
2502
    }//if
2503
    
2504
    // if no error and no success info, send a error that nothing happened
2505
    if( !error && !success)
2506
    {
2507
      out.println(ERROR);
2508
      out.println("Nothing happend for setaccess action");
2509
      out.println(ERRORCLOSE);
2510
    }
2511
    
2512
  }//outputResponse
2513
}
(37-37/54)