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: jones $'
10
 *     '$Date: 2004-03-26 15:25:53 -0800 (Fri, 26 Mar 2004) $'
11
 * '$Revision: 2067 $'
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
import edu.ucsb.nceas.utilities.Options;
70

    
71
import org.xml.sax.SAXException;
72

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

    
110
  private ServletConfig config = null;
111
  private ServletContext context = null;
112
  private String resultStyleURL = null;
113
  private String xmlcatalogfile = null;
114
  private String saxparser = null;
115
  private String datafilepath = null;
116
  private File dataDirectory = null;
117
  private String servletpath = null;
118
  private String htmlpath = null;
119
  private PropertyResourceBundle options = null;
120
  private MetaCatUtil util = null;
121
  private DBConnectionPool connPool = null;
122
  private Hashtable sessionHash = new Hashtable();
123
  private static final String PROLOG = "<?xml version=\"1.0\"?>";
124
  private static final String SUCCESS = "<success>";
125
  private static final String SUCCESSCLOSE = "</success>";
126
  private static final String ERROR = "<error>";
127
  private static final String ERRORCLOSE = "</error>";
128
  public static final String SCHEMALOCATIONKEYWORD = ":schemaLocation";
129
  public static final String NONAMESPACELOCATION = ":noNamespaceSchemaLocation";
130
  public static final String EML2KEYWORD =":eml";
131
  private static final String CONFIG_DIR  = "WEB-INF";
132
  private static final String CONFIG_NAME = "metacat.properties";
133

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

    
144
      // Initialize the properties file for our options
145
      String dirPath = context.getRealPath(CONFIG_DIR);
146
      File propertyFile = new File(dirPath,CONFIG_NAME);
147
      Options options = null;
148
      try {
149
          options = Options.initialize(propertyFile);
150
          MetaCatUtil.debugMessage("Options configured: " + 
151
            options.getOption("configured"), 20);
152
      } catch (IOException ioe) {
153
        MetaCatUtil.debugMessage("Error in loading options: "
154
           +ioe.getMessage(), 20);
155
      }
156

    
157
      util = new MetaCatUtil();
158

    
159
      //initial DBConnection pool
160
      connPool = DBConnectionPool.getInstance();
161

    
162
      // Get the configuration file information
163
      resultStyleURL = util.getOption("resultStyleURL");
164
      xmlcatalogfile = util.getOption("xmlcatalogfile");
165
      saxparser = util.getOption("saxparser");
166
      datafilepath = util.getOption("datafilepath");
167
      dataDirectory = new File(datafilepath);
168
      servletpath = util.getOption("servletpath");
169
      htmlpath = util.getOption("htmlpath");
170

    
171

    
172
    } catch ( ServletException ex ) {
173
      throw ex;
174
    } catch (SQLException e) {
175
      MetaCatUtil.debugMessage("Error in MetacatServlet.init: "
176
                                          +e.getMessage(), 20);
177
    }
178
  }
179

    
180
  /**
181
   * Close all db connections from the pool
182
   */
183
  public void destroy() {
184
      // Close all db connection
185
      System.out.println("Destroying MetacatServlet");
186
      connPool.release();
187
  }
188

    
189
  /** Handle "GET" method requests from HTTP clients */
190
  public void doGet (HttpServletRequest request, HttpServletResponse response)
191
    throws ServletException, IOException {
192

    
193
    // Process the data and send back the response
194
    handleGetOrPost(request, response);
195
  }
196

    
197
  /** Handle "POST" method requests from HTTP clients */
198
  public void doPost( HttpServletRequest request, HttpServletResponse response)
199
    throws ServletException, IOException {
200

    
201
    // Process the data and send back the response
202
    handleGetOrPost(request, response);
203
  }
204

    
205
  /**
206
   * Control servlet response depending on the action parameter specified
207
   */
208
  private void handleGetOrPost(HttpServletRequest request,
209
                               HttpServletResponse response)
210
                               throws ServletException, IOException
211
  {
212

    
213
    if ( util == null ) {
214
        util = new MetaCatUtil();
215
    }
216
    /*MetaCatUtil.debugMessage("Connection pool size: "
217
                                     +connPool.getSizeOfDBConnectionPool(),10);
218
    MetaCatUtil.debugMessage("Free DBConnection number: "
219
                                  +connPool.getFreeDBConnectionNumber(), 10);*/
220
    //If all DBConnection in the pool are free and DBConnection pool
221
    //size is greater than initial value, shrink the connection pool
222
    //size to initial value
223
    DBConnectionPool.shrinkDBConnectionPoolSize();
224

    
225
    //Debug message to print out the method which have a busy DBConnection
226
    connPool.printMethodNameHavingBusyDBConnection();
227

    
228
    String ctype = request.getContentType();
229
    if (ctype != null && ctype.startsWith("multipart/form-data")) {
230
      handleMultipartForm(request, response);
231
    } else {
232

    
233

    
234
      String name = null;
235
      String[] value = null;
236
      String[] docid = new String[3];
237
      Hashtable params = new Hashtable();
238
      Enumeration paramlist = request.getParameterNames();
239

    
240

    
241
      while (paramlist.hasMoreElements()) {
242

    
243
        name = (String)paramlist.nextElement();
244
        value = request.getParameterValues(name);
245

    
246
        // Decode the docid and mouse click information
247
        if (name.endsWith(".y")) {
248
          docid[0] = name.substring(0,name.length()-2);
249
          params.put("docid", docid);
250
          name = "ypos";
251
        }
252
        if (name.endsWith(".x")) {
253
          name = "xpos";
254
        }
255

    
256
        params.put(name,value);
257
      }
258

    
259

    
260
      //handle param is emptpy
261
      if (params.isEmpty() || params == null)
262
      {
263
        return;
264
      }
265

    
266
      //if the user clicked on the input images, decode which image
267
      //was clicked then set the action.
268
      String action = ((String[])params.get("action"))[0];
269
      util.debugMessage("Line 230: Action is: " + action, 1);
270

    
271
      // This block handles session management for the servlet
272
      // by looking up the current session information for all actions
273
      // other than "login" and "logout"
274
      String username = null;
275
      String password = null;
276
      String[] groupnames = null;
277
      String sess_id = null;
278

    
279
      // handle login action
280
      if (action.equals("login")) {
281
        PrintWriter out = response.getWriter();
282
        handleLoginAction(out, params, request, response);
283
        out.close();
284

    
285
      // handle logout action
286
      } else if (action.equals("logout")) {
287
        PrintWriter out = response.getWriter();
288
        handleLogoutAction(out, params, request, response);
289
        out.close();
290

    
291
      // handle shrink DBConnection request
292
      } else if (action.equals("shrink")) {
293
        PrintWriter out = response.getWriter();
294
        boolean success = false;
295
        //If all DBConnection in the pool are free and DBConnection pool
296
        //size is greater than initial value, shrink the connection pool
297
        //size to initial value
298
        success = DBConnectionPool.shrinkConnectionPoolSize();
299
        if (success)
300
        {
301
          //if successfully shrink the pool size to initial value
302
          out.println("DBConnection Pool shrink successfully");
303
        }//if
304
        else
305
        {
306
          out.println("DBConnection pool couldn't shrink successfully");
307
        }
308
       //close out put
309
        out.close();
310

    
311
      // aware of session expiration on every request
312
      }
313
      else
314
      {
315
        HttpSession sess = request.getSession(true);
316
        if (sess.isNew() && !params.containsKey("sessionid")) {
317
          // session expired or has not been stored b/w user requests
318
          MetaCatUtil.debugMessage("in session is new or no sessionid", 40);
319
          username = "public";
320
          sess.setAttribute("username", username);
321
        }
322
        else
323
        {
324
          MetaCatUtil.debugMessage("in session is not new or " + 
325
                                    " has sessionid parameter", 40);
326
          try
327
          {
328
            if(params.containsKey("sessionid"))
329
            {
330
              sess_id = ((String[])params.get("sessionid"))[0];
331
              MetaCatUtil.debugMessage("in has sessionid " + sess_id, 40);
332
              if(sessionHash.containsKey(sess_id))
333
              {
334
                MetaCatUtil.debugMessage("find the id " + sess_id + 
335
                                         " in hash table", 40);
336
                sess = (HttpSession)sessionHash.get(sess_id);
337
              }
338
            }
339
            else
340
            {
341
              // we already store the session in login, so we don't need here
342
              /*MetaCatUtil.debugMessage("in no sessionid parameter ", 40);
343
              sess_id = (String)sess.getId();
344
              MetaCatUtil.debugMessage("storing the session id "+ sess_id +
345
                  " which has username " + sess.getAttribute("username") + 
346
                 " into session hash in handleGetOrPost method", 35);
347
              sessionHash.put(sess_id, sess);*/
348
            }
349
          }
350
          catch(IllegalStateException ise)
351
          {
352
            System.out.println("error in handleGetOrPost: this shouldn't " +
353
                               "happen: the session should be valid: " +
354
                               ise.getMessage());
355
          }
356

    
357
          username = (String)sess.getAttribute("username");
358
          MetaCatUtil.debugMessage("The user name from session is: "+
359
                                   username, 20);
360
          password = (String)sess.getAttribute("password");
361
          groupnames = (String[])sess.getAttribute("groupnames");
362
        }
363
      
364
        //make user user username should be public
365
        if (username == null || (username.trim().equals("")))
366
        {
367
          username = "public";
368
        }
369
        MetaCatUtil.debugMessage("The user is : "+ username, 5);
370
      }
371
       // Now that we know the session is valid, we can delegate the request
372
      // to a particular action handler
373
      if(action.equals("query")) {
374
        PrintWriter out = response.getWriter();
375
        handleQuery(out,params,response,username,groupnames,sess_id);
376
        out.close();
377
      } else if(action.equals("squery")) {
378
        PrintWriter out = response.getWriter();
379
        if(params.containsKey("query")) {
380
         handleSQuery(out, params,response,username,groupnames,sess_id);
381
         out.close();
382
        } else {
383
          out.println("Illegal action squery without \"query\" parameter");
384
          out.close();
385
        }
386
      } else if (action.equals("export")) {
387

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

    
493
      //util.closeConnections();
494
      // Close the stream to the client
495
      //out.close();
496
    }
497
  }
498

    
499
  // LOGIN & LOGOUT SECTION
500
  /**
501
   * Handle the login request. Create a new session object.
502
   * Do user authentication through the session.
503
   */
504
  private void handleLoginAction(PrintWriter out, Hashtable params,
505
               HttpServletRequest request, HttpServletResponse response) {
506

    
507
    AuthSession sess = null;
508
    String un = ((String[])params.get("username"))[0];
509
    MetaCatUtil.debugMessage("user " + un + " try to login", 20);
510
    String pw = ((String[])params.get("password"))[0];
511
    String action = ((String[])params.get("action"))[0];
512
    String qformat = ((String[])params.get("qformat"))[0];
513

    
514
    try {
515
      sess = new AuthSession();
516
    } catch (Exception e) {
517
      System.out.println("error in MetacatServlet.handleLoginAction: " +
518
                          e.getMessage());
519
      out.println(e.getMessage());
520
      return;
521
    }
522
    boolean isValid = sess.authenticate(request, un, pw);
523
    
524
    //if it is authernticate is true, store the session
525
    if (isValid)
526
    {
527
      HttpSession session = sess.getSessions();
528
      String id = session.getId();
529
      MetaCatUtil.debugMessage("Store session id " + id + 
530
               "which has username" + session.getAttribute("username")+
531
               " into hash in login method", 35);
532
      sessionHash.put(id, session);
533
    }
534
    
535
    // format and transform the output
536
    if (qformat.equals("xml")) {
537
      response.setContentType("text/xml");
538
      out.println(sess.getMessage());
539
    } else {
540

    
541
      try {
542

    
543
        DBTransform trans = new DBTransform();
544
        response.setContentType("text/html");
545
        trans.transformXMLDocument(sess.getMessage(), "-//NCEAS//login//EN",
546
                                   "-//W3C//HTML//EN", qformat, out, null);
547

    
548
      } catch(Exception e) {
549

    
550
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLoginAction: "
551
                                +e.getMessage(), 30);
552
      }
553

    
554
    // any output is returned
555
    }
556
  }
557

    
558
  /**
559
   * Handle the logout request. Close the connection.
560
   */
561
  private void handleLogoutAction(PrintWriter out, Hashtable params,
562
               HttpServletRequest request, HttpServletResponse response) {
563

    
564
    String qformat = ((String[])params.get("qformat"))[0];
565

    
566
    // close the connection
567
    HttpSession sess = request.getSession(false);
568
    MetaCatUtil.debugMessage("After get session in logout request", 40);
569
    if (sess != null) 
570
    {
571
     MetaCatUtil.debugMessage("The session id " + sess.getId() + 
572
                              " will be invalidate in logout action", 30);
573
     MetaCatUtil.debugMessage("The session contains user " + 
574
                               sess.getAttribute("username") +
575
                               " will be invalidate in logout action", 30);
576
      sess.invalidate();  
577
    }
578

    
579
    // produce output
580
    StringBuffer output = new StringBuffer();
581
    output.append("<?xml version=\"1.0\"?>");
582
    output.append("<logout>");
583
    output.append("User logged out");
584
    output.append("</logout>");
585

    
586
    //format and transform the output
587
    if (qformat.equals("xml")) {
588
      response.setContentType("text/xml");
589
      out.println(output.toString());
590
    } else {
591

    
592
      try {
593

    
594
        DBTransform trans = new DBTransform();
595
        response.setContentType("text/html");
596
        trans.transformXMLDocument(output.toString(), "-//NCEAS//login//EN",
597
                                   "-//W3C//HTML//EN", qformat, out, null);
598

    
599
      } catch(Exception e) {
600

    
601
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLogoutAction"
602
                                  +e.getMessage(), 30);
603
      }
604
    }
605
  }
606
  // END OF LOGIN & LOGOUT SECTION
607

    
608
  // SQUERY & QUERY SECTION
609
  /**
610
   * Retreive the squery xml, execute it and display it
611
   *
612
   * @param out the output stream to the client
613
   * @param params the Hashtable of parameters that should be included
614
   * in the squery.
615
   * @param response the response object linked to the client
616
   * @param conn the database connection
617
   */
618
  protected void handleSQuery(PrintWriter out, Hashtable params,
619
                 HttpServletResponse response, String user, String[] groups,
620
                 String sessionid)
621
  {
622
    String xmlquery = ((String[])params.get("query"))[0];
623
    String qformat = ((String[])params.get("qformat"))[0];
624
    String resultdoc = null;
625
    MetaCatUtil.debugMessage("xmlquery: "+xmlquery, 30);
626
    double startTime = System.currentTimeMillis()/1000;
627
    Hashtable doclist = runQuery(xmlquery, user, groups);
628
    double docListTime = System.currentTimeMillis()/1000;
629
    MetaCatUtil.debugMessage("Time for getting doc list: "
630
                                            +(docListTime-startTime), 30);
631

    
632
    resultdoc = createResultDocument(doclist, transformQuery(xmlquery));
633
    double toStringTime = System.currentTimeMillis()/1000;
634
    MetaCatUtil.debugMessage("Time to create xml string: "
635
                              +(toStringTime-docListTime), 30);
636
    //format and transform the results
637
    double outPutTime = 0;
638
    if(qformat.equals("xml")) {
639
      response.setContentType("text/xml");
640
      out.println(resultdoc);
641
      outPutTime = System.currentTimeMillis()/1000;
642
      MetaCatUtil.debugMessage("Output time: "+(outPutTime-toStringTime), 30);
643
    } else {
644
      transformResultset(resultdoc, response, out, qformat, sessionid, params);
645
      outPutTime = System.currentTimeMillis()/1000;
646
      MetaCatUtil.debugMessage("Output time: "+(outPutTime-toStringTime), 30);
647
    }
648
  }
649

    
650
   /**
651
    * Create the xml query, execute it and display the results.
652
    *
653
    * @param out the output stream to the client
654
    * @param params the Hashtable of parameters that should be included
655
    * in the squery.
656
    * @param response the response object linked to the client
657
    */
658
  protected void handleQuery(PrintWriter out, Hashtable params,
659
                 HttpServletResponse response, String user, String[] groups,
660
                 String sessionid)
661
  {
662
    //create the query and run it
663
    String xmlquery = DBQuery.createSQuery(params);
664
    Hashtable doclist = runQuery(xmlquery, user, groups);
665
    String qformat = ((String[])params.get("qformat"))[0];
666
    String resultdoc = null;
667

    
668
    resultdoc = createResultDocument(doclist, transformQuery(params));
669

    
670
    //format and transform the results
671
    if(qformat.equals("xml")) {
672
      response.setContentType("text/xml");
673
      out.println(resultdoc);
674
    } else {
675
      transformResultset(resultdoc, response, out, qformat, sessionid, params);
676
    }
677
  }
678

    
679
  /**
680
   * Removes the <?xml version="x"?> tag from the beginning of xmlquery
681
   * so it can properly be placed in the <query> tag of the resultset.
682
   * This method is overwritable so that other applications can customize
683
   * the structure of what is in the <query> tag.
684
   *
685
   * @param xmlquery is the query to remove the <?xml version="x"?> tag from.
686
   */
687
  protected String transformQuery(Hashtable params)
688
  {
689
    //DBQuery.createSQuery is a re-calling of a previously called
690
    //function but it is necessary
691
    //so that overriding methods have access to the params hashtable
692
    String xmlquery = DBQuery.createSQuery(params);
693
    //the <?xml version="1.0"?> tag is the first 22 characters of the
694
    xmlquery = xmlquery.trim();
695
    int index = xmlquery.indexOf("?>");
696
    if ( index != -1 )
697
    {
698
      //have <?xml version="1.0"?>
699
      return xmlquery.substring(index + 2, xmlquery.length());
700
    }
701
    else
702
    {
703
      // don't have <?xml version="1.0"?>
704
      return xmlquery;
705
    }
706
  }
707

    
708
  /**
709
   * removes the <?xml version="1.0"?> tag from the beginning.  This takes a
710
   * string as a param instead of a hashtable.
711
   *
712
   * @param xmlquery a string representing a query.
713
   */
714
  protected String transformQuery(String xmlquery)
715
  {
716
    xmlquery = xmlquery.trim();
717
    int index = xmlquery.indexOf("?>");
718
    if (index != -1)
719
    {
720
      return xmlquery.substring(index + 2, xmlquery.length());
721
    }
722
    else
723
    {
724
      return xmlquery;
725
    }
726
  }
727

    
728
  /**
729
   * Run the query and return a hashtable of results.
730
   *
731
   * @param xmlquery the query to run
732
   */
733
  private Hashtable runQuery(String xmlquery, String user, String[] groups)
734
  {
735
    Hashtable doclist=null;
736

    
737
    try
738
    {
739

    
740
      DBQuery queryobj = new DBQuery(saxparser);
741
      doclist = queryobj.findDocuments(new StringReader(xmlquery),user,groups);
742

    
743
      return doclist;
744
    }
745
    catch (Exception e)
746
    {
747

    
748
      MetaCatUtil.debugMessage("Error in MetacatServlet.runQuery: "
749
                                                      + e.getMessage(), 30);
750
      doclist = null;
751
      return doclist;
752
    }
753
  }
754

    
755
  /**
756
   * Transorms an xml resultset document to html and sends it to the browser
757
   *
758
   * @param resultdoc the string representation of the document that needs
759
   * to be transformed.
760
   * @param response the HttpServletResponse object bound to the client.
761
   * @param out the output stream to the client
762
   * @param qformat the name of the style-set to use for transformations
763
   */
764
  protected void transformResultset(String resultdoc,
765
                                    HttpServletResponse response,
766
                                    PrintWriter out, String qformat,
767
                                    String sessionid, Hashtable params)
768
  {
769

    
770
    try {
771

    
772
      DBTransform trans = new DBTransform();
773
      response.setContentType("text/html");
774
      trans.transformXMLDocument(resultdoc, "-//NCEAS//resultset//EN",
775
                                 "-//W3C//HTML//EN", qformat, out, params,
776
                                 sessionid);
777

    
778
    }
779
    catch(Exception e)
780
    {
781

    
782
      MetaCatUtil.debugMessage("Error in MetaCatServlet.transformResultset:"
783
                                +e.getMessage(), 30);
784
    }
785
  }
786

    
787
  /**
788
   * Transforms a hashtable of documents to an xml or html result.
789
   *
790
   * @param doclist- the hashtable to transform
791
   * @param xmlquery- the query that returned the doclist result
792
   */
793
  protected String createResultDocument(Hashtable doclist, String xmlquery)
794
  {
795
    // Create a buffer to hold the xml result
796
    StringBuffer resultset = new StringBuffer();
797

    
798
    // Print the resulting root nodes
799
    String docid = null;
800
    String document = null;
801
    resultset.append("<?xml version=\"1.0\"?>\n");
802
    resultset.append("<resultset>\n");
803

    
804
    resultset.append("  <query>" + xmlquery + "</query>");
805

    
806
    if(doclist != null)
807
    {
808
      Enumeration doclistkeys = doclist.keys();
809
      while (doclistkeys.hasMoreElements())
810
      {
811
        docid = (String)doclistkeys.nextElement();
812
        document = (String)doclist.get(docid);
813
        resultset.append("  <document>" + document + "</document>");
814
      }
815
    }
816

    
817
    resultset.append("</resultset>");
818
    return resultset.toString();
819
  }
820
  // END OF SQUERY & QUERY SECTION
821

    
822
 //Exoport section
823
 /**
824
   * Handle the "export" request of data package from Metacat in zip format
825
   * @param params the Hashtable of HTTP request parameters
826
   * @param response the HTTP response object linked to the client
827
   * @param user the username sent the request
828
   * @param groups the user's groupnames
829
   */
830
  private void handleExportAction(Hashtable params,
831
    HttpServletResponse response, String user, String[] groups, String passWord)
832
  {
833
    // Output stream
834
    ServletOutputStream out = null;
835
    // Zip output stream
836
    ZipOutputStream zOut = null;
837
    DocumentImpl docImpls=null;
838
    DBQuery queryObj=null;
839

    
840
    String[] docs = new String[10];
841
    String docId = "";
842

    
843
    try
844
    {
845
      // read the params
846
      if (params.containsKey("docid"))
847
      {
848
        docs = (String[])params.get("docid");
849
      }//if
850
      // Create a DBuery to handle export
851
      queryObj = new DBQuery(saxparser);
852
      // Get the docid
853
      docId=docs[0];
854
      // Make sure the client specify docid
855
      if (docId == null || docId.equals(""))
856
      {
857
        response.setContentType("text/xml"); //MIME type
858
        // Get a printwriter
859
        PrintWriter pw = response.getWriter();
860
        // Send back message
861
        pw.println("<?xml version=\"1.0\"?>");
862
        pw.println("<error>");
863
        pw.println("You didn't specify requested docid");
864
        pw.println("</error>");
865
        // Close printwriter
866
        pw.close();
867
        return;
868
      }//if
869
      // Get output stream
870
      out = response.getOutputStream();
871
      response.setContentType("application/zip"); //MIME type
872
      zOut = new ZipOutputStream(out);
873
      zOut =queryObj.getZippedPackage(docId, out, user, groups, passWord);
874
      zOut.finish(); //terminate the zip file
875
      zOut.close();  //close the zip stream
876

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

    
909
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleExportAction: " +
910
                         e.getMessage(), 30);
911
      e.printStackTrace(System.out);
912

    
913
    }//catch
914

    
915
  }//handleExportAction
916

    
917

    
918
   //read inline data section
919
 /**
920
   * In eml2 document, the xml can have inline data and data was stripped off
921
   * and store in file system. This action can be used to read inline data only
922
   * @param params the Hashtable of HTTP request parameters
923
   * @param response the HTTP response object linked to the client
924
   * @param user the username sent the request
925
   * @param groups the user's groupnames
926
   */
927
  private void handleReadInlineDataAction(Hashtable params,
928
                                          HttpServletResponse response,
929
                                          String user, String passWord,
930
                                          String[] groups)
931
  {
932
    String[] docs = new String[10];
933
    String inlineDataId = null;
934
    String docId = "";
935
    ServletOutputStream out = null;
936

    
937
    try
938
    {
939
      // read the params
940
      if (params.containsKey("inlinedataid"))
941
      {
942
        docs = (String[])params.get("inlinedataid");
943
      }//if
944
      // Get the docid
945
      inlineDataId=docs[0];
946
      // Make sure the client specify docid
947
      if (inlineDataId == null || inlineDataId.equals(""))
948
      {
949
        throw new Exception("You didn't specify requested inlinedataid");
950
      }//if
951

    
952
      // check for permission
953
      docId = MetaCatUtil.getDocIdWithoutRevFromInlineDataID(inlineDataId);
954
      PermissionController controller = new PermissionController(docId);
955
      // check top level read permission
956
      if (!controller.hasPermission(user, groups,
957
                                    AccessControlInterface.READSTRING))
958
      {
959
          throw new Exception("User "+ user + " doesn't have permission "+
960
                              " to read document " + docId);
961
      }//if
962
      // if the document has subtree control, we need to check subtree control
963
      else if(controller.hasSubTreeAccessControl())
964
      {
965
        // get node id for inlinedata
966
        long nodeId=getInlineDataNodeId(inlineDataId, docId);
967
        if (!controller.hasPermissionForSubTreeNode(user, groups,
968
                                     AccessControlInterface.READSTRING, nodeId))
969
        {
970
           throw new Exception("User "+ user + " doesn't have permission "+
971
                              " to read inlinedata " + inlineDataId);
972
        }//if
973

    
974
      }//else
975

    
976
      // Get output stream
977
      out = response.getOutputStream();
978
      // read the inline data from the file
979
      String inlinePath = MetaCatUtil.getOption("inlinedatafilepath");
980
      File lineData = new File(inlinePath, inlineDataId);
981
      FileInputStream input = new FileInputStream(lineData);
982
      byte [] buffer = new byte[4*1024];
983
      int bytes = input.read(buffer);
984
      while (bytes != -1)
985
      {
986
        out.write(buffer, 0, bytes);
987
        bytes = input.read(buffer);
988
      }
989
      out.close();
990

    
991
    }//try
992
    catch (Exception e)
993
    {
994
      try
995
      {
996
        PrintWriter pw = null;
997
        // Send error message back
998
        if (out != null)
999
        {
1000
            pw = new PrintWriter(out);
1001
        }//if
1002
        else
1003
        {
1004
          pw = response.getWriter();
1005
        }
1006
         pw.println("<?xml version=\"1.0\"?>");
1007
         pw.println("<error>");
1008
         pw.println(e.getMessage());
1009
         pw.println("</error>");
1010
         // Close printwriter
1011
         pw.close();
1012
         // Close output stream if out is not null
1013
         if (out != null)
1014
         {
1015
           out.close();
1016
         }
1017
     }//try
1018
     catch (IOException ioe)
1019
     {
1020
        MetaCatUtil.debugMessage("Problem with the servlet output " +
1021
                           "in MetacatServlet.handleExportAction: " +
1022
                           ioe.getMessage(), 30);
1023
     }//catch
1024

    
1025
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleReadInlineDataAction: "
1026
                                + e.getMessage(), 30);
1027

    
1028
    }//catch
1029

    
1030
  }//handleReadInlineDataAction
1031

    
1032
  /*
1033
   * Get the nodeid from xml_nodes for the inlinedataid
1034
   */
1035
  private long getInlineDataNodeId(String inLineDataId, String docId)
1036
                                   throws SQLException
1037
  {
1038
    long nodeId = 0;
1039
    String INLINE = "inline";
1040
    boolean hasRow;
1041
    PreparedStatement pStmt = null;
1042
    DBConnection conn = null;
1043
    int serialNumber = -1;
1044
    String sql ="SELECT nodeid FROM xml_nodes WHERE docid=? AND nodedata=? " +
1045
                "AND nodetype='TEXT' AND parentnodeid IN " +
1046
                "(SELECT nodeid FROM xml_nodes WHERE docid=? AND " +
1047
                "nodetype='ELEMENT' AND nodename='" + INLINE + "')";
1048

    
1049
    try
1050
    {
1051
      //check out DBConnection
1052
      conn=DBConnectionPool.getDBConnection("AccessControlList.isAllowFirst");
1053
      serialNumber=conn.getCheckOutSerialNumber();
1054

    
1055
      pStmt = conn.prepareStatement(sql);
1056
      //bind value
1057
      pStmt.setString(1, docId);//docid
1058
      pStmt.setString(2, inLineDataId);//inlinedataid
1059
      pStmt.setString(3, docId);
1060
      // excute query
1061
      pStmt.execute();
1062
      ResultSet rs = pStmt.getResultSet();
1063
      hasRow=rs.next();
1064
      // get result
1065
      if (hasRow)
1066
      {
1067
        nodeId = rs.getLong(1);
1068
      }//if
1069

    
1070
    }//try
1071
    catch (SQLException e)
1072
    {
1073
      throw e;
1074
    }
1075
    finally
1076
    {
1077
      try
1078
      {
1079
        pStmt.close();
1080
      }
1081
      finally
1082
      {
1083
        DBConnectionPool.returnDBConnection(conn, serialNumber);
1084
      }
1085
    }
1086
    MetaCatUtil.debugMessage("The nodeid for inlinedataid " + inLineDataId +
1087
                             " is: "+nodeId, 35);
1088
    return nodeId;
1089
  }
1090

    
1091

    
1092

    
1093
  // READ SECTION
1094
  /**
1095
   * Handle the "read" request of metadata/data files from Metacat
1096
   * or any files from Internet;
1097
   * transformed metadata XML document into HTML presentation if requested;
1098
   * zip files when more than one were requested.
1099
   *
1100
   * @param params the Hashtable of HTTP request parameters
1101
   * @param response the HTTP response object linked to the client
1102
   * @param user the username sent the request
1103
   * @param groups the user's groupnames
1104
   */
1105
  private void handleReadAction(Hashtable params, HttpServletResponse response,
1106
                                String user, String passWord, String[] groups)
1107
  {
1108
    ServletOutputStream out = null;
1109
    ZipOutputStream zout = null;
1110
    PrintWriter pw = null;
1111
    boolean zip = false;
1112
    boolean withInlineData = true;
1113

    
1114
    try {
1115
      String[] docs = new String[0];
1116
      String docid = "";
1117
      String qformat = "";
1118
      String abstrpath = null;
1119

    
1120
      // read the params
1121
      if (params.containsKey("docid")) {
1122
        docs = (String[])params.get("docid");
1123
      }
1124
      if (params.containsKey("qformat")) {
1125
        qformat = ((String[])params.get("qformat"))[0];
1126
      }
1127
      // the param for only metadata (eml)
1128
      if (params.containsKey("inlinedata"))
1129
      {
1130

    
1131
        String inlineData = ((String[])params.get("inlinedata"))[0];
1132
        if (inlineData.equalsIgnoreCase("false"))
1133
        {
1134
          withInlineData = false;
1135
        }
1136
      }
1137
      if (params.containsKey("abstractpath")) {
1138
        abstrpath = ((String[])params.get("abstractpath"))[0];
1139
        if ( !abstrpath.equals("") && (abstrpath != null) ) {
1140
          viewAbstract(response, abstrpath, docs[0]);
1141
          return;
1142
        }
1143
      }
1144
      if ( (docs.length > 1) || qformat.equals("zip") ) {
1145
        zip = true;
1146
        out = response.getOutputStream();
1147
        response.setContentType("application/zip"); //MIME type
1148
        zout = new ZipOutputStream(out);
1149
      }
1150
      // go through the list of docs to read
1151
      for (int i=0; i < docs.length; i++ ) {
1152
        try {
1153

    
1154
          URL murl = new URL(docs[i]);
1155
          Hashtable murlQueryStr = util.parseQuery(murl.getQuery());
1156
          // case docid="http://.../?docid=aaa"
1157
          // or docid="metacat://.../?docid=bbb"
1158
          if (murlQueryStr.containsKey("docid")) {
1159
            // get only docid, eliminate the rest
1160
            docid = (String)murlQueryStr.get("docid");
1161
            if ( zip ) {
1162
              addDocToZip(docid, zout, user, groups);
1163
            } else {
1164
              readFromMetacat(response, docid, qformat, abstrpath,
1165
                              user, groups, zip, zout, withInlineData, params);
1166
            }
1167

    
1168
          // case docid="http://.../filename"
1169
          } else {
1170
            docid = docs[i];
1171
            if ( zip ) {
1172
              addDocToZip(docid, zout, user, groups);
1173
            } else {
1174
              readFromURLConnection(response, docid);
1175
            }
1176
          }
1177

    
1178
        // case docid="ccc"
1179
        } catch (MalformedURLException mue) {
1180
          docid = docs[i];
1181
          if ( zip ) {
1182
            addDocToZip(docid, zout, user, groups);
1183
          } else {
1184
            readFromMetacat(response, docid, qformat, abstrpath,
1185
                            user, groups, zip, zout, withInlineData, params);
1186
          }
1187
        }
1188

    
1189
      } /* end for */
1190

    
1191
      if ( zip ) {
1192
        zout.finish(); //terminate the zip file
1193
        zout.close();  //close the zip stream
1194
      }
1195

    
1196

    
1197
    }
1198
    // To handle doc not found exception
1199
    catch (McdbDocNotFoundException notFoundE)
1200
    {
1201
      // the docid which didn't be found
1202
      String notFoundDocId = notFoundE.getUnfoundDocId();
1203
      String notFoundRevision = notFoundE.getUnfoundRevision();
1204
      MetaCatUtil.debugMessage("Missed id: "+ notFoundDocId, 30);
1205
      MetaCatUtil.debugMessage("Missed rev: "+ notFoundRevision, 30);
1206
      try
1207
      {
1208
        // read docid from remote server
1209
        readFromRemoteMetaCat(response, notFoundDocId, notFoundRevision,
1210
                                              user, passWord, out, zip, zout);
1211
        // Close zout outputstream
1212
        if ( zout != null)
1213
        {
1214
          zout.close();
1215
        }
1216
        // close output stream
1217
        if (out != null)
1218
        {
1219
          out.close();
1220
        }
1221

    
1222
      }//try
1223
      catch ( Exception exc)
1224
      {
1225
        MetaCatUtil.debugMessage("Erorr in MetacatServlet.hanldReadAction: "+
1226
                                      exc.getMessage(), 30);
1227
        try
1228
        {
1229
          if (out != null)
1230
          {
1231
            response.setContentType("text/xml");
1232
            // Send back error message by printWriter
1233
            pw = new PrintWriter(out);
1234
            pw.println("<?xml version=\"1.0\"?>");
1235
            pw.println("<error>");
1236
            pw.println(notFoundE.getMessage());
1237
            pw.println("</error>");
1238
            pw.close();
1239
            out.close();
1240

    
1241
          }
1242
          else
1243
          {
1244
           response.setContentType("text/xml"); //MIME type
1245
           // Send back error message if out = null
1246
           if (pw == null)
1247
           {
1248
             // If pw is null, open the respnose
1249
            pw = response.getWriter();
1250
           }
1251
           pw.println("<?xml version=\"1.0\"?>");
1252
           pw.println("<error>");
1253
           pw.println(notFoundE.getMessage());
1254
           pw.println("</error>");
1255
           pw.close();
1256
        }
1257
        // close zout
1258
        if ( zout != null )
1259
        {
1260
          zout.close();
1261
        }
1262
        }//try
1263
        catch (IOException ie)
1264
        {
1265
          MetaCatUtil.debugMessage("Problem with the servlet output " +
1266
                           "in MetacatServlet.handleReadAction: " +
1267
                           ie.getMessage(), 30);
1268
        }//cathch
1269
      }//catch
1270
    }// catch McdbDocNotFoundException
1271
    catch (Exception e)
1272
    {
1273
      try {
1274

    
1275
        if (out != null) {
1276
            response.setContentType("text/xml"); //MIME type
1277
            pw = new PrintWriter(out);
1278
            pw.println("<?xml version=\"1.0\"?>");
1279
            pw.println("<error>");
1280
            pw.println(e.getMessage());
1281
            pw.println("</error>");
1282
            pw.close();
1283
            out.close();
1284
        }
1285
        else
1286
        {
1287
           response.setContentType("text/xml"); //MIME type
1288
           // Send back error message if out = null
1289
           if ( pw == null)
1290
           {
1291
            pw = response.getWriter();
1292
           }
1293
           pw.println("<?xml version=\"1.0\"?>");
1294
           pw.println("<error>");
1295
           pw.println(e.getMessage());
1296
           pw.println("</error>");
1297
           pw.close();
1298

    
1299
        }
1300
        // Close zip output stream
1301
        if ( zout != null ) { zout.close(); }
1302

    
1303
      } catch (IOException ioe) {
1304
        MetaCatUtil.debugMessage("Problem with the servlet output " +
1305
                           "in MetacatServlet.handleReadAction: " +
1306
                           ioe.getMessage(), 30);
1307
        ioe.printStackTrace(System.out);
1308

    
1309
      }
1310

    
1311
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleReadAction: " +
1312
                               e.getMessage(), 30);
1313
      //e.printStackTrace(System.out);
1314
    }
1315

    
1316
  }
1317

    
1318
  // read metadata or data from Metacat
1319
  private void readFromMetacat(HttpServletResponse response, String docid,
1320
                               String qformat, String abstrpath, String user,
1321
                               String[] groups, boolean zip,
1322
                               ZipOutputStream zout, boolean withInlineData,
1323
                               Hashtable params)
1324
               throws ClassNotFoundException, IOException, SQLException,
1325
                      McdbException, Exception
1326
  {
1327

    
1328
    try {
1329

    
1330

    
1331
      DocumentImpl doc = new DocumentImpl(docid);
1332

    
1333
      //check the permission for read
1334
      if (!doc.hasReadPermission(user, groups, docid))
1335
      {
1336
        Exception e = new Exception("User " + user + " does not have permission"
1337
                       +" to read the document with the docid " + docid);
1338

    
1339
        throw e;
1340
      }
1341

    
1342
      if ( doc.getRootNodeID() == 0 ) {
1343
        // this is data file
1344
        String filepath = util.getOption("datafilepath");
1345
        if(!filepath.endsWith("/")) {
1346
          filepath += "/";
1347
        }
1348
        String filename = filepath + docid;
1349
        FileInputStream fin = null;
1350
        fin = new FileInputStream(filename);
1351

    
1352
        //MIME type
1353
        String contentType = getServletContext().getMimeType(filename);
1354
        if (contentType == null)
1355
        {
1356
          ContentTypeProvider provider = new ContentTypeProvider(docid);
1357
          contentType = provider.getContentType();
1358
          MetaCatUtil.debugMessage("Final contenttype is: "+ contentType, 30);
1359
        }
1360

    
1361
        response.setContentType(contentType);
1362
        // if we decide to use "application/octet-stream" for all data returns
1363
        // response.setContentType("application/octet-stream");
1364

    
1365
        try {
1366

    
1367
          ServletOutputStream out = response.getOutputStream();
1368
          byte[] buf = new byte[4 * 1024]; // 4K buffer
1369
          int b = fin.read(buf);
1370
          while (b != -1) {
1371
            out.write(buf, 0, b);
1372
            b = fin.read(buf);
1373
          }
1374
        } finally {
1375
          if (fin != null) fin.close();
1376
        }
1377

    
1378
      } else {
1379
        // this is metadata doc
1380
        if ( qformat.equals("xml") ) {
1381

    
1382
          // set content type first
1383
          response.setContentType("text/xml");   //MIME type
1384
          PrintWriter out = response.getWriter();
1385
          doc.toXml(out, user, groups, withInlineData);
1386
        } else {
1387
          response.setContentType("text/html");  //MIME type
1388
          PrintWriter out = response.getWriter();
1389

    
1390
          // Look up the document type
1391
          String doctype = doc.getDoctype();
1392
          // Transform the document to the new doctype
1393
          DBTransform dbt = new DBTransform();
1394
          dbt.transformXMLDocument(doc.toString(user, groups, withInlineData),
1395
                                   doctype,"-//W3C//HTML//EN",
1396
                                   qformat, out, params);
1397
        }
1398

    
1399
      }
1400
    }
1401
    catch (Exception except)
1402
    {
1403
      throw except;
1404

    
1405
    }
1406

    
1407
  }
1408

    
1409
  // read data from URLConnection
1410
  private void readFromURLConnection(HttpServletResponse response, String docid)
1411
               throws IOException, MalformedURLException
1412
  {
1413
    ServletOutputStream out = response.getOutputStream();
1414
    String contentType = getServletContext().getMimeType(docid); //MIME type
1415
    if (contentType == null) {
1416
      if (docid.endsWith(".xml")) {
1417
        contentType="text/xml";
1418
      } else if (docid.endsWith(".css")) {
1419
        contentType="text/css";
1420
      } else if (docid.endsWith(".dtd")) {
1421
        contentType="text/plain";
1422
      } else if (docid.endsWith(".xsd")) {
1423
        contentType="text/xml";
1424
      } else if (docid.endsWith("/")) {
1425
        contentType="text/html";
1426
      } else {
1427
        File f = new File(docid);
1428
        if ( f.isDirectory() ) {
1429
          contentType="text/html";
1430
        } else {
1431
          contentType="application/octet-stream";
1432
        }
1433
      }
1434
    }
1435
    response.setContentType(contentType);
1436
    // if we decide to use "application/octet-stream" for all data returns
1437
    // response.setContentType("application/octet-stream");
1438

    
1439
    // this is http url
1440
    URL url = new URL(docid);
1441
    BufferedInputStream bis = null;
1442
    try {
1443
      bis = new BufferedInputStream(url.openStream());
1444
      byte[] buf = new byte[4 * 1024]; // 4K buffer
1445
      int b = bis.read(buf);
1446
      while (b != -1) {
1447
        out.write(buf, 0, b);
1448
        b = bis.read(buf);
1449
      }
1450
    } finally {
1451
      if (bis != null) bis.close();
1452
    }
1453

    
1454
  }
1455

    
1456
  // read file/doc and write to ZipOutputStream
1457
  private void addDocToZip(String docid, ZipOutputStream zout,
1458
                              String user, String[] groups)
1459
               throws ClassNotFoundException, IOException, SQLException,
1460
                      McdbException, Exception
1461
  {
1462
    byte[] bytestring = null;
1463
    ZipEntry zentry = null;
1464

    
1465
    try {
1466
      URL url = new URL(docid);
1467

    
1468
      // this http url; read from URLConnection; add to zip
1469
      zentry = new ZipEntry(docid);
1470
      zout.putNextEntry(zentry);
1471
      BufferedInputStream bis = null;
1472
      try {
1473
        bis = new BufferedInputStream(url.openStream());
1474
        byte[] buf = new byte[4 * 1024]; // 4K buffer
1475
        int b = bis.read(buf);
1476
        while(b != -1) {
1477
          zout.write(buf, 0, b);
1478
          b = bis.read(buf);
1479
        }
1480
      } finally {
1481
        if (bis != null) bis.close();
1482
      }
1483
      zout.closeEntry();
1484

    
1485
    } catch (MalformedURLException mue) {
1486

    
1487
      // this is metacat doc (data file or metadata doc)
1488

    
1489
      try {
1490

    
1491
        DocumentImpl doc = new DocumentImpl(docid);
1492

    
1493
        //check the permission for read
1494
        if (!doc.hasReadPermission(user, groups, docid))
1495
        {
1496
          Exception e = new Exception("User " + user + " does not have "
1497
                    +"permission to read the document with the docid " + docid);
1498

    
1499
          throw e;
1500
        }
1501

    
1502
        if ( doc.getRootNodeID() == 0 ) {
1503
          // this is data file; add file to zip
1504
          String filepath = util.getOption("datafilepath");
1505
          if(!filepath.endsWith("/")) {
1506
            filepath += "/";
1507
          }
1508
          String filename = filepath + docid;
1509
          FileInputStream fin = null;
1510
          fin = new FileInputStream(filename);
1511
          try {
1512

    
1513
            zentry = new ZipEntry(docid);
1514
            zout.putNextEntry(zentry);
1515
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1516
            int b = fin.read(buf);
1517
            while (b != -1) {
1518
              zout.write(buf, 0, b);
1519
              b = fin.read(buf);
1520
            }
1521
          } finally {
1522
            if (fin != null) fin.close();
1523
          }
1524
          zout.closeEntry();
1525

    
1526
        } else {
1527
          // this is metadata doc; add doc to zip
1528
          bytestring = doc.toString().getBytes();
1529
          zentry = new ZipEntry(docid + ".xml");
1530
          zentry.setSize(bytestring.length);
1531
          zout.putNextEntry(zentry);
1532
          zout.write(bytestring, 0, bytestring.length);
1533
          zout.closeEntry();
1534
        }
1535
      } catch (Exception except) {
1536
        throw except;
1537

    
1538
      }
1539

    
1540
    }
1541

    
1542
  }
1543

    
1544
  // view abstract within document
1545
  private void viewAbstract(HttpServletResponse response,
1546
                            String abstractpath, String docid)
1547
               throws ClassNotFoundException, IOException, SQLException,
1548
                      McdbException, Exception
1549
  {
1550

    
1551
    PrintWriter out =null;
1552
    try {
1553

    
1554
      response.setContentType("text/html");  //MIME type
1555
      out = response.getWriter();
1556
      Object[] abstracts = DBQuery.getNodeContent(abstractpath, docid);
1557
      out.println("<html><head><title>Abstract</title></head>");
1558
      out.println("<body bgcolor=\"white\"><h1>Abstract</h1>");
1559
      for (int i=0; i<abstracts.length; i++) {
1560
        out.println("<p>" + (String)abstracts[i] + "</p>");
1561
      }
1562
      out.println("</body></html>");
1563

    
1564
    } catch (Exception e) {
1565
       out.println("<?xml version=\"1.0\"?>");
1566
       out.println("<error>");
1567
       out.println(e.getMessage());
1568
       out.println("</error>");
1569

    
1570

    
1571
    }
1572
  }
1573
  /**
1574
   * If metacat couldn't find a data file or document locally, it will read this
1575
   * docid from its home server. This is for the replication feature
1576
   */
1577
  private void readFromRemoteMetaCat(HttpServletResponse response, String docid,
1578
                     String rev, String user, String password,
1579
                     ServletOutputStream out, boolean zip, ZipOutputStream zout)
1580
                        throws Exception
1581
 {
1582
   // Create a object of RemoteDocument, "" is for zipEntryPath
1583
   RemoteDocument remoteDoc =
1584
                        new RemoteDocument (docid, rev,user, password, "");
1585
   String docType = remoteDoc.getDocType();
1586
   // Only read data file
1587
   if (docType.equals("BIN"))
1588
   {
1589
    // If it is zip format
1590
    if (zip)
1591
    {
1592
      remoteDoc.readDocumentFromRemoteServerByZip(zout);
1593
    }//if
1594
    else
1595
    {
1596
      if (out == null)
1597
      {
1598
        out = response.getOutputStream();
1599
      }//if
1600
      response.setContentType("application/octet-stream");
1601
      remoteDoc.readDocumentFromRemoteServer(out);
1602
    }//else (not zip)
1603
   }//if doctype=bin
1604
   else
1605
   {
1606
     throw new Exception("Docid: "+docid+"."+rev+" couldn't find");
1607
   }//else
1608
 }//readFromRemoteMetaCat
1609

    
1610
  // END OF READ SECTION
1611

    
1612

    
1613

    
1614
  // INSERT/UPDATE SECTION
1615
  /**
1616
   * Handle the database putdocument request and write an XML document
1617
   * to the database connection
1618
   */
1619
  private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params,
1620
               String user, String[] groups) {
1621

    
1622
    DBConnection dbConn = null;
1623
    int serialNumber = -1;
1624

    
1625
    try {
1626
      // Get the document indicated
1627
      String[] doctext = (String[])params.get("doctext");
1628

    
1629
      String pub = null;
1630
      if (params.containsKey("public")) {
1631
        pub = ((String[])params.get("public"))[0];
1632
      }
1633

    
1634
      StringReader dtd = null;
1635
      if (params.containsKey("dtdtext")) {
1636
        String[] dtdtext = (String[])params.get("dtdtext");
1637
        try {
1638
          if ( !dtdtext[0].equals("") ) {
1639
            dtd = new StringReader(dtdtext[0]);
1640
          }
1641
        } catch (NullPointerException npe) {}
1642
      }
1643

    
1644
      StringReader xml = new StringReader(doctext[0]);
1645
      boolean validate = false;
1646
      DocumentImplWrapper documentWrapper = null;
1647
      try {
1648
        // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1649
        // in order to decide whether to use validation parser
1650
        validate = needDTDValidation(xml);
1651
        if (validate)
1652
        {
1653
          // set a dtd base validation parser
1654
          String rule = DocumentImpl.DTD;
1655
          documentWrapper = new DocumentImplWrapper(rule, validate);
1656
        }
1657
        else if (needSchemaValidation(xml))
1658
        {
1659
          // for eml2
1660
          if (needEml2Validation(xml))
1661
          {
1662
             // set eml2 base validation parser
1663
            String rule = DocumentImpl.EML2;
1664
            // using emlparser to check id validation
1665
            EMLParser parser = new EMLParser(doctext[0]);
1666
            documentWrapper = new DocumentImplWrapper(rule, true);
1667
          }
1668
          else
1669
          {
1670
            // set schema base validation parser
1671
            String rule = DocumentImpl.SCHEMA;
1672
            documentWrapper = new DocumentImplWrapper(rule, true);
1673
          }
1674
        }
1675
        else
1676
        {
1677
          documentWrapper = new DocumentImplWrapper("", false);
1678
        }
1679

    
1680
        String[] action = (String[])params.get("action");
1681
        String[] docid = (String[])params.get("docid");
1682
        String newdocid = null;
1683

    
1684
        String doAction = null;
1685
        if (action[0].equals("insert")) {
1686
          doAction = "INSERT";
1687
        } else if (action[0].equals("update")) {
1688
          doAction = "UPDATE";
1689
        }
1690

    
1691
        try
1692
        {
1693
          // get a connection from the pool
1694
          dbConn=DBConnectionPool.
1695
                  getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1696
          serialNumber=dbConn.getCheckOutSerialNumber();
1697

    
1698
           // write the document to the database
1699
          try
1700
          {
1701
            String accNumber = docid[0];
1702
            MetaCatUtil.debugMessage(""+ doAction + " " + accNumber +"...", 10);
1703
            if (accNumber.equals(""))
1704
            {
1705
              accNumber = null;
1706
            }//if
1707
            newdocid = documentWrapper.write(dbConn, xml, pub, dtd, doAction,
1708
                                          accNumber, user, groups);
1709

    
1710
          }//try
1711
          catch (NullPointerException npe)
1712
          {
1713
            newdocid = documentWrapper.write(dbConn, xml, pub, dtd, doAction,
1714
                                          null, user, groups);
1715
          }//catch
1716

    
1717
        }//try
1718
        finally
1719
        {
1720
          // Return db connection
1721
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1722
        }
1723

    
1724
        // set content type and other response header fields first
1725
        //response.setContentType("text/xml");
1726
        out.println("<?xml version=\"1.0\"?>");
1727
        out.println("<success>");
1728
        out.println("<docid>" + newdocid + "</docid>");
1729
        out.println("</success>");
1730

    
1731
      }
1732
      catch (NullPointerException npe)
1733
      {
1734
        //response.setContentType("text/xml");
1735
        out.println("<?xml version=\"1.0\"?>");
1736
        out.println("<error>");
1737
        out.println(npe.getMessage());
1738
        out.println("</error>");
1739
      }
1740
    }
1741
    catch (Exception e)
1742
    {
1743
      //response.setContentType("text/xml");
1744
      out.println("<?xml version=\"1.0\"?>");
1745
      out.println("<error>");
1746
      out.println(e.getMessage());
1747
      out.println("</error>");
1748
    }
1749
  }
1750

    
1751
  /**
1752
   * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1753
   * in order to decide whether to use validation parser
1754
   */
1755
  private static boolean needDTDValidation(StringReader xmlreader) throws 
1756
                                                             IOException 
1757
  {
1758

    
1759
    
1760
    StringBuffer cbuff = new StringBuffer();
1761
    java.util.Stack st = new java.util.Stack();
1762
    boolean validate = false;
1763
    int c;
1764
    int inx;
1765

    
1766
    // read from the stream until find the keywords
1767
    while ( (st.empty() || st.size()<4) && ((c = xmlreader.read()) != -1) ) {
1768
      cbuff.append((char)c);
1769

    
1770
      // "<!DOCTYPE" keyword is found; put it in the stack
1771
      if ( (inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1 ) {
1772
        cbuff = new StringBuffer();
1773
        st.push("<!DOCTYPE");
1774
      }
1775
      // "PUBLIC" keyword is found; put it in the stack
1776
      if ( (inx = cbuff.toString().indexOf("PUBLIC")) != -1 ) {
1777
        cbuff = new StringBuffer();
1778
        st.push("PUBLIC");
1779
      }
1780
      // "SYSTEM" keyword is found; put it in the stack
1781
      if ( (inx = cbuff.toString().indexOf("SYSTEM")) != -1 ) {
1782
        cbuff = new StringBuffer();
1783
        st.push("SYSTEM");
1784
      }
1785
      // ">" character is found; put it in the stack
1786
      // ">" is found twice: fisrt from <?xml ...?>
1787
      // and second from <!DOCTYPE ... >
1788
      if ( (inx = cbuff.toString().indexOf(">")) != -1 ) {
1789
        cbuff = new StringBuffer();
1790
        st.push(">");
1791
      }
1792
    }
1793

    
1794
    // close the stream
1795
    xmlreader.reset();
1796

    
1797
    // check the stack whether it contains the keywords:
1798
    // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1799
    if ( st.size() == 4 ) {
1800
      if ( ((String)st.pop()).equals(">") &&
1801
           ( ((String)st.peek()).equals("PUBLIC") |
1802
             ((String)st.pop()).equals("SYSTEM") ) &&
1803
           ((String)st.pop()).equals("<!DOCTYPE") )  {
1804
        validate = true;
1805
      }
1806
    }
1807

    
1808
    MetaCatUtil.debugMessage("Validation for dtd is " + validate, 10);
1809
    return validate;
1810
  }
1811
  // END OF INSERT/UPDATE SECTION
1812

    
1813
  /* check if the xml string contains key words to specify schema loocation*/
1814
  private boolean needSchemaValidation(StringReader xml) throws IOException
1815
  {
1816
    boolean needSchemaValidate =false;
1817
    if (xml == null)
1818
    {
1819
      MetaCatUtil.debugMessage("Validation for schema is " +
1820
                               needSchemaValidate, 10);
1821
      return needSchemaValidate;
1822
    }
1823
    System.out.println("before get target line");
1824
    String targetLine = getSchemaLine(xml);
1825
    System.out.println("before get target line");
1826
    // to see if the second line contain some keywords
1827
    if (targetLine != null && (targetLine.indexOf(SCHEMALOCATIONKEYWORD) != -1||
1828
             targetLine.indexOf(NONAMESPACELOCATION) != -1 ))
1829
    {
1830
      // if contains schema location key word, should be validate
1831
      needSchemaValidate = true;
1832
    }
1833

    
1834
    MetaCatUtil.debugMessage("Validation for schema is " +
1835
                             needSchemaValidate, 10);
1836
    return needSchemaValidate;
1837

    
1838
  }
1839

    
1840
   /* check if the xml string contains key words to specify schema loocation*/
1841
  private boolean needEml2Validation(StringReader xml) throws IOException
1842
  {
1843
    boolean needEml2Validate =false;
1844
    String emlNameSpace =DocumentImpl.EMLNAMESPACE;
1845
    String schemaLocationContent = null;
1846
    if (xml == null)
1847
    {
1848
      MetaCatUtil.debugMessage("Validation for schema is " +
1849
                               needEml2Validate, 10);
1850
      return needEml2Validate;
1851
    }
1852
    String targetLine = getSchemaLine(xml);
1853

    
1854
    if (targetLine != null)
1855
    {
1856
      
1857
      int startIndex = targetLine.indexOf(SCHEMALOCATIONKEYWORD);
1858
      int start = 1;
1859
      int end   = 1;
1860
      String schemaLocation = null;
1861
      int count = 0;
1862
      if (startIndex != -1)
1863
      {
1864
        for ( int i=startIndex; i<targetLine.length(); i++)
1865
        {
1866
          if (targetLine.charAt(i) =='"')
1867
          {
1868
            count ++;
1869
          }
1870
          if (targetLine.charAt(i) =='"' && count == 1)
1871
          {
1872
            start = i;
1873
          }
1874
          if (targetLine.charAt(i) =='"' && count == 2)
1875
          {
1876
            end = i;
1877
            break;
1878
          }
1879
        }
1880
      }
1881
      schemaLocation = targetLine.substring(start+1, end);
1882
      MetaCatUtil.debugMessage("schemaLocation in xml is: "+schemaLocation, 30);
1883
      if ( schemaLocation.indexOf(emlNameSpace) != -1)
1884
      {
1885
        needEml2Validate = true;
1886
      }
1887
    }
1888

    
1889
    MetaCatUtil.debugMessage("Validation for eml is " +
1890
                             needEml2Validate, 10);
1891
    return needEml2Validate;
1892

    
1893
  }
1894

    
1895
  private String getSchemaLine(StringReader xml) throws IOException
1896
  {
1897
    // find the line
1898
    String secondLine = null;
1899
    int count =0;
1900
    int endIndex = 0;
1901
    int startIndex = 0;
1902
    final int TARGETNUM = 2;
1903
    StringBuffer buffer = new StringBuffer();
1904
    boolean comment =false;
1905
    char thirdPreviousCharacter = '?';
1906
    char secondPreviousCharacter ='?';
1907
    char previousCharacter = '?';
1908
    char currentCharacter = '?';
1909
    
1910
    while ( (currentCharacter = (char) xml.read()) != -1)
1911
    {
1912
      //in a comment
1913
      if (currentCharacter =='-' && previousCharacter == '-'  && 
1914
          secondPreviousCharacter =='!' && thirdPreviousCharacter == '<')
1915
      {
1916
        comment = true;
1917
      }
1918
      //out of comment
1919
      if (comment && currentCharacter == '>' && previousCharacter == '-' && 
1920
          secondPreviousCharacter =='-')
1921
      {
1922
         comment = false;
1923
      }
1924
      
1925
      //this is not comment
1926
      if (currentCharacter !='!' && previousCharacter == '<' && !comment)
1927
      {
1928
        count ++;
1929
      }
1930
      // get target line
1931
      if (count == TARGETNUM && currentCharacter !='>')
1932
      {
1933
        buffer.append(currentCharacter);
1934
      }
1935
      if (count == TARGETNUM && currentCharacter == '>')
1936
      {
1937
          break;
1938
      }
1939
      thirdPreviousCharacter = secondPreviousCharacter;
1940
      secondPreviousCharacter = previousCharacter;
1941
      previousCharacter = currentCharacter;
1942
      
1943
    }
1944
    secondLine = buffer.toString();
1945
    MetaCatUtil.debugMessage("the second line string is: "+secondLine, 25);
1946
    xml.reset();
1947
    return secondLine;
1948
  }
1949

    
1950
  // DELETE SECTION
1951
  /**
1952
   * Handle the database delete request and delete an XML document
1953
   * from the database connection
1954
   */
1955
  private void handleDeleteAction(PrintWriter out, Hashtable params,
1956
               HttpServletResponse response, String user, String[] groups) {
1957

    
1958
    String[] docid = (String[])params.get("docid");
1959

    
1960
    // delete the document from the database
1961
    try {
1962

    
1963
                                      // NOTE -- NEED TO TEST HERE
1964
                                      // FOR EXISTENCE OF DOCID PARAM
1965
                                      // BEFORE ACCESSING ARRAY
1966
      try {
1967
        DocumentImpl.delete(docid[0], user, groups);
1968
        response.setContentType("text/xml");
1969
        out.println("<?xml version=\"1.0\"?>");
1970
        out.println("<success>");
1971
        out.println("Document deleted.");
1972
        out.println("</success>");
1973
      } catch (AccessionNumberException ane) {
1974
        response.setContentType("text/xml");
1975
        out.println("<?xml version=\"1.0\"?>");
1976
        out.println("<error>");
1977
        out.println("Error deleting document!!!");
1978
        out.println(ane.getMessage());
1979
        out.println("</error>");
1980
      }
1981
    } catch (Exception e) {
1982
      response.setContentType("text/xml");
1983
      out.println("<?xml version=\"1.0\"?>");
1984
      out.println("<error>");
1985
      out.println(e.getMessage());
1986
      out.println("</error>");
1987
    }
1988
  }
1989
  // END OF DELETE SECTION
1990

    
1991
  // VALIDATE SECTION
1992
  /**
1993
   * Handle the validation request and return the results to the requestor
1994
   */
1995
  private void handleValidateAction(PrintWriter out, Hashtable params) {
1996

    
1997
    // Get the document indicated
1998
    String valtext = null;
1999
    DBConnection dbConn = null;
2000
    int serialNumber = -1;
2001

    
2002
    try {
2003
      valtext = ((String[])params.get("valtext"))[0];
2004
    } catch (Exception nullpe) {
2005

    
2006

    
2007
      String docid = null;
2008
      try {
2009
        // Find the document id number
2010
        docid = ((String[])params.get("docid"))[0];
2011

    
2012

    
2013
        // Get the document indicated from the db
2014
        DocumentImpl xmldoc = new DocumentImpl(docid);
2015
        valtext = xmldoc.toString();
2016

    
2017
      } catch (NullPointerException npe) {
2018

    
2019
        out.println("<error>Error getting document ID: " + docid + "</error>");
2020
        //if ( conn != null ) { util.returnConnection(conn); }
2021
        return;
2022
      } catch (Exception e) {
2023

    
2024
        out.println(e.getMessage());
2025
      }
2026
    }
2027

    
2028

    
2029
    try {
2030
      // get a connection from the pool
2031
      dbConn=DBConnectionPool.
2032
                  getDBConnection("MetaCatServlet.handleValidateAction");
2033
      serialNumber=dbConn.getCheckOutSerialNumber();
2034
      DBValidate valobj = new DBValidate(saxparser,dbConn);
2035
      boolean valid = valobj.validateString(valtext);
2036

    
2037
      // set content type and other response header fields first
2038

    
2039
      out.println(valobj.returnErrors());
2040

    
2041
    } catch (NullPointerException npe2) {
2042
      // set content type and other response header fields first
2043

    
2044
      out.println("<error>Error validating document.</error>");
2045
    } catch (Exception e) {
2046

    
2047
      out.println(e.getMessage());
2048
    } finally {
2049
      // Return db connection
2050
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2051
    }
2052
  }
2053
  // END OF VALIDATE SECTION
2054

    
2055
  // OTHER ACTION HANDLERS
2056

    
2057
  /**
2058
   * Handle "getrevsionanddoctype" action
2059
   * Given a docid, return it's current revision and doctype from data base
2060
   * The output is String look like "rev;doctype"
2061
   */
2062
  private void handleGetRevisionAndDocTypeAction(PrintWriter out,
2063
                                                              Hashtable params)
2064
  {
2065
    // To store doc parameter
2066
    String [] docs = new String[10];
2067
    // Store a single doc id
2068
    String givenDocId = null;
2069
    // Get docid from parameters
2070
    if (params.containsKey("docid"))
2071
    {
2072
      docs = (String[])params.get("docid");
2073
    }
2074
    // Get first docid form string array
2075
    givenDocId = docs[0];
2076

    
2077
    try
2078
    {
2079
      // Make sure there is a docid
2080
      if (givenDocId == null || givenDocId.equals(""))
2081
      {
2082
        throw new Exception("User didn't specify docid!");
2083
      }//if
2084

    
2085
      // Create a DBUtil object
2086
      DBUtil dbutil = new DBUtil();
2087
      // Get a rev and doctype
2088
      String revAndDocType =
2089
                dbutil.getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
2090
      out.println(revAndDocType);
2091

    
2092
    }//try
2093
    catch (Exception e)
2094
    {
2095
      // Handle exception
2096
      out.println("<?xml version=\"1.0\"?>");
2097
      out.println("<error>");
2098
      out.println(e.getMessage());
2099
      out.println("</error>");
2100
    }//catch
2101

    
2102
  }//handleGetRevisionAndDocTypeAction
2103

    
2104
  /**
2105
   * Handle "getaccesscontrol" action.
2106
   * Read Access Control List from db connection in XML format
2107
   */
2108
  private void handleGetAccessControlAction(PrintWriter out, Hashtable params,
2109
                                       HttpServletResponse response,
2110
                                       String username, String[] groupnames) {
2111

    
2112
    DBConnection dbConn = null;
2113
    int serialNumber = -1;
2114
    String docid = ((String[])params.get("docid"))[0];
2115

    
2116
    try {
2117

    
2118
        // get connection from the pool
2119
        dbConn=DBConnectionPool.
2120
                 getDBConnection("MetaCatServlet.handleGetAccessControlAction");
2121
        serialNumber=dbConn.getCheckOutSerialNumber();
2122
        AccessControlList aclobj = new AccessControlList(dbConn);
2123
        String acltext = aclobj.getACL(docid, username, groupnames);
2124
        out.println(acltext);
2125

    
2126
    } catch (Exception e) {
2127
      out.println("<?xml version=\"1.0\"?>");
2128
      out.println("<error>");
2129
      out.println(e.getMessage());
2130
      out.println("</error>");
2131
    } finally {
2132
      // Retrun db connection to pool
2133
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2134
    }
2135

    
2136
  }
2137

    
2138
  /**
2139
   * Handle the "getprincipals" action.
2140
   * Read all principals from authentication scheme in XML format
2141
   */
2142
  private void handleGetPrincipalsAction(PrintWriter out, String user,
2143
                                         String password) {
2144

    
2145

    
2146
    try {
2147

    
2148

    
2149
        AuthSession auth = new AuthSession();
2150
        String principals = auth.getPrincipals(user, password);
2151
        out.println(principals);
2152

    
2153
    } catch (Exception e) {
2154
      out.println("<?xml version=\"1.0\"?>");
2155
      out.println("<error>");
2156
      out.println(e.getMessage());
2157
      out.println("</error>");
2158
    }
2159

    
2160
  }
2161

    
2162
  /**
2163
   * Handle "getdoctypes" action.
2164
   * Read all doctypes from db connection in XML format
2165
   */
2166
  private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
2167
                                       HttpServletResponse response) {
2168

    
2169

    
2170
    try {
2171

    
2172

    
2173
        DBUtil dbutil = new DBUtil();
2174
        String doctypes = dbutil.readDoctypes();
2175
        out.println(doctypes);
2176

    
2177
    } catch (Exception e) {
2178
      out.println("<?xml version=\"1.0\"?>");
2179
      out.println("<error>");
2180
      out.println(e.getMessage());
2181
      out.println("</error>");
2182
    }
2183

    
2184
  }
2185

    
2186
  /**
2187
   * Handle the "getdtdschema" action.
2188
   * Read DTD or Schema file for a given doctype from Metacat catalog system
2189
   */
2190
  private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
2191
                                        HttpServletResponse response) {
2192

    
2193

    
2194
    String doctype = null;
2195
    String[] doctypeArr = (String[])params.get("doctype");
2196

    
2197
    // get only the first doctype specified in the list of doctypes
2198
    // it could be done for all doctypes in that list
2199
    if (doctypeArr != null) {
2200
        doctype = ((String[])params.get("doctype"))[0];
2201
    }
2202

    
2203
    try {
2204

    
2205

    
2206
        DBUtil dbutil = new DBUtil();
2207
        String dtdschema = dbutil.readDTDSchema(doctype);
2208
        out.println(dtdschema);
2209

    
2210
    } catch (Exception e) {
2211
      out.println("<?xml version=\"1.0\"?>");
2212
      out.println("<error>");
2213
      out.println(e.getMessage());
2214
      out.println("</error>");
2215
    }
2216

    
2217
  }
2218

    
2219
  /**
2220
   * Handle the "getlastdocid" action.
2221
   * Get the latest docid with rev number from db connection in XML format
2222
   */
2223
  private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
2224
                                        HttpServletResponse response) {
2225

    
2226

    
2227
    String scope = ((String[])params.get("scope"))[0];
2228
    if (scope == null) {
2229
        scope = ((String[])params.get("username"))[0];
2230
    }
2231

    
2232
    try {
2233

    
2234

    
2235
        DBUtil dbutil = new DBUtil();
2236
        String lastDocid = dbutil.getMaxDocid(scope);
2237
        out.println("<?xml version=\"1.0\"?>");
2238
        out.println("<lastDocid>");
2239
        out.println("  <scope>" + scope + "</scope>");
2240
        out.println("  <docid>" + lastDocid + "</docid>");
2241
        out.println("</lastDocid>");
2242

    
2243
    } catch (Exception e) {
2244
      out.println("<?xml version=\"1.0\"?>");
2245
      out.println("<error>");
2246
      out.println(e.getMessage());
2247
      out.println("</error>");
2248
    }
2249

    
2250
  }
2251

    
2252
  /**
2253
   * Handle documents passed to metacat that are encoded using the
2254
   * "multipart/form-data" mime type.  This is typically used for uploading
2255
   * data files which may be binary and large.
2256
   */
2257
  private void handleMultipartForm(HttpServletRequest request,
2258
                                   HttpServletResponse response)
2259
  {
2260
    PrintWriter out = null;
2261
    String action = null;
2262

    
2263
    // Parse the multipart form, and save the parameters in a Hashtable and
2264
    // save the FileParts in a hashtable
2265

    
2266
    Hashtable params = new Hashtable();
2267
    Hashtable fileList = new Hashtable();
2268
    int sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit")))
2269
                                                                   .intValue();
2270
    MetaCatUtil.debugMessage("The limit size of data file is: "+sizeLimit, 50);
2271

    
2272
    try {
2273
      // MBJ: need to put filesize limit in Metacat config (metacat.properties)
2274
      MultipartParser mp = new MultipartParser(request, sizeLimit*1024*1024);
2275
      Part part;
2276
      while ((part = mp.readNextPart()) != null) {
2277
        String name = part.getName();
2278

    
2279
        if (part.isParam()) {
2280
          // it's a parameter part
2281
          ParamPart paramPart = (ParamPart) part;
2282
          String value = paramPart.getStringValue();
2283
          params.put(name, value);
2284
          if (name.equals("action")) {
2285
            action = value;
2286
          }
2287
        } else if (part.isFile()) {
2288
          // it's a file part
2289
          FilePart filePart = (FilePart) part;
2290
          fileList.put(name, filePart);
2291

    
2292
          // Stop once the first file part is found, otherwise going onto the
2293
          // next part prevents access to the file contents.  So...for upload
2294
          // to work, the datafile must be the last part
2295
          break;
2296
        }
2297
      }
2298
    } catch (IOException ioe) {
2299
      try {
2300
        out = response.getWriter();
2301
      } catch (IOException ioe2) {
2302
        System.err.println("Fatal Error: couldn't get response output stream.");
2303
      }
2304
      out.println("<?xml version=\"1.0\"?>");
2305
      out.println("<error>");
2306
      out.println("Error: problem reading multipart data.");
2307
      out.println("</error>");
2308
    }
2309

    
2310
    // Get the session information
2311
    String username = null;
2312
    String password = null;
2313
    String[] groupnames = null;
2314
    String sess_id = null;
2315

    
2316
    // be aware of session expiration on every request
2317
    HttpSession sess = request.getSession(true);
2318
    if (sess.isNew()) {
2319
      // session expired or has not been stored b/w user requests
2320
      username = "public";
2321
      sess.setAttribute("username", username);
2322
    } else {
2323
      username = (String)sess.getAttribute("username");
2324
      password = (String)sess.getAttribute("password");
2325
      groupnames = (String[])sess.getAttribute("groupnames");
2326
      try {
2327
        sess_id = (String)sess.getId();
2328
      } catch(IllegalStateException ise) {
2329
        System.out.println("error in  handleMultipartForm: this shouldn't " +
2330
                           "happen: the session should be valid: " +
2331
                           ise.getMessage());
2332
      }
2333
    }
2334

    
2335
    // Get the out stream
2336
    try {
2337
          out = response.getWriter();
2338
        } catch (IOException ioe2) {
2339
          util.debugMessage("Fatal Error: couldn't get response "+
2340
                             "output stream.", 30);
2341
        }
2342

    
2343
    if ( action.equals("upload")) {
2344
      if (username != null &&  !username.equals("public")) {
2345
        handleUploadAction(request, out, params, fileList,
2346
                           username, groupnames);
2347
      } else {
2348

    
2349
        out.println("<?xml version=\"1.0\"?>");
2350
        out.println("<error>");
2351
        out.println("Permission denied for " + action);
2352
        out.println("</error>");
2353
      }
2354
    } else {
2355
      /*try {
2356
        out = response.getWriter();
2357
      } catch (IOException ioe2) {
2358
        System.err.println("Fatal Error: couldn't get response output stream.");
2359
      }*/
2360
      out.println("<?xml version=\"1.0\"?>");
2361
      out.println("<error>");
2362
      out.println("Error: action not registered.  Please report this error.");
2363
      out.println("</error>");
2364
    }
2365
    out.close();
2366
  }
2367

    
2368
  /**
2369
   * Handle the upload action by saving the attached file to disk and
2370
   * registering it in the Metacat db
2371
   */
2372
  private void handleUploadAction(HttpServletRequest request,
2373
                                  PrintWriter out,
2374
                                  Hashtable params, Hashtable fileList,
2375
                                  String username, String[] groupnames)
2376
  {
2377
    //PrintWriter out = null;
2378
    //Connection conn = null;
2379
    String action = null;
2380
    String docid = null;
2381

    
2382
    /*response.setContentType("text/xml");
2383
    try
2384
    {
2385
      out = response.getWriter();
2386
    }
2387
    catch (IOException ioe2)
2388
    {
2389
      System.err.println("Fatal Error: couldn't get response output stream.");
2390
    }*/
2391

    
2392
    if (params.containsKey("docid"))
2393
    {
2394
      docid = (String)params.get("docid");
2395
    }
2396

    
2397
    // Make sure we have a docid and datafile
2398
    if (docid != null && fileList.containsKey("datafile")) {
2399

    
2400
      // Get a reference to the file part of the form
2401
      FilePart filePart = (FilePart)fileList.get("datafile");
2402
      String fileName = filePart.getFileName();
2403
      MetaCatUtil.debugMessage("Uploading filename: " + fileName, 10);
2404

    
2405
      // Check if the right file existed in the uploaded data
2406
      if (fileName != null) {
2407

    
2408
        try
2409
        {
2410
           //MetaCatUtil.debugMessage("Upload datafile " + docid +"...", 10);
2411
           //If document get lock data file grant
2412
           if (DocumentImpl.getDataFileLockGrant(docid))
2413
           {
2414
              // register the file in the database (which generates an exception
2415
              //if the docid is not acceptable or other untoward things happen
2416
              DocumentImpl.registerDocument(fileName, "BIN", docid, username);
2417

    
2418
              // Save the data file to disk using "docid" as the name
2419
              dataDirectory.mkdirs();
2420
              File newFile = new File(dataDirectory, docid);
2421
              long size = filePart.writeTo(newFile);
2422

    
2423
              // Force replication this data file
2424
              // To data file, "insert" and update is same
2425
              // The fourth parameter is null. Because it is notification server
2426
              // and this method is in MetaCatServerlet. It is original command,
2427
              // not get force replication info from another metacat
2428
              ForceReplicationHandler frh = new ForceReplicationHandler
2429
                                                (docid, "insert", false, null);
2430

    
2431
              // set content type and other response header fields first
2432
              out.println("<?xml version=\"1.0\"?>");
2433
              out.println("<success>");
2434
              out.println("<docid>" + docid + "</docid>");
2435
              out.println("<size>" + size + "</size>");
2436
              out.println("</success>");
2437
          }//if
2438

    
2439
        } //try
2440
        catch (Exception e)
2441
        {
2442
          out.println("<?xml version=\"1.0\"?>");
2443
          out.println("<error>");
2444
          out.println(e.getMessage());
2445
          out.println("</error>");
2446
        }
2447

    
2448
      }
2449
      else
2450
      {
2451
        // the field did not contain a file
2452
        out.println("<?xml version=\"1.0\"?>");
2453
        out.println("<error>");
2454
        out.println("The uploaded data did not contain a valid file.");
2455
        out.println("</error>");
2456
      }
2457
    }
2458
    else
2459
    {
2460
      // Error bcse docid missing or file missing
2461
      out.println("<?xml version=\"1.0\"?>");
2462
      out.println("<error>");
2463
      out.println("The uploaded data did not contain a valid docid " +
2464
                  "or valid file.");
2465
      out.println("</error>");
2466
    }
2467
  }
2468

    
2469
  /*
2470
   * A method to handle set access action
2471
   */
2472
  private void handleSetAccessAction(PrintWriter out,
2473
                                   Hashtable params,
2474
                                   String username)
2475
  {
2476
    String [] docList        = null;
2477
    String [] principalList  = null;
2478
    String [] permissionList = null;
2479
    String [] permTypeList   = null;
2480
    String [] permOrderList  = null;
2481
    String permission = null;
2482
    String permType   = null;
2483
    String permOrder  = null;
2484
    Vector errorList  = new Vector();
2485
    String error      = null;
2486
    Vector successList = new Vector();
2487
    String success    = null;
2488

    
2489

    
2490
    // Get parameters
2491
    if (params.containsKey("docid"))
2492
    {
2493
      docList = (String[])params.get("docid");
2494
    }
2495
    if (params.containsKey("principal"))
2496
    {
2497
      principalList = (String[])params.get("principal");
2498
    }
2499
    if (params.containsKey("permission"))
2500
    {
2501
      permissionList = (String[])params.get("permission");
2502

    
2503
    }
2504
    if (params.containsKey("permType"))
2505
    {
2506
      permTypeList = (String[])params.get("permType");
2507

    
2508
    }
2509
    if (params.containsKey("permOrder"))
2510
    {
2511
      permOrderList = (String[])params.get("permOrder");
2512

    
2513
    }
2514

    
2515
    // Make sure the parameter is not null
2516
    if (docList == null || principalList == null || permTypeList == null ||
2517
        permissionList == null)
2518
    {
2519
      error = "Please check your parameter list, it should look like: "+
2520
              "?action=setaccess&docid=pipeline.1.1&principal=public" +
2521
              "&permission=read&permType=allow&permOrder=allowFirst";
2522
      errorList.addElement(error);
2523
      outputResponse(successList, errorList, out);
2524
      return;
2525
    }
2526

    
2527
    // Only select first element for permission, type and order
2528
    permission = permissionList[0];
2529
    permType = permTypeList[0];
2530
    if (permOrderList != null)
2531
    {
2532
       permOrder = permOrderList[0];
2533
    }
2534

    
2535
    // Get package doctype set
2536
    Vector packageSet =MetaCatUtil.getOptionList(
2537
                                    MetaCatUtil.getOption("packagedoctypeset"));
2538
    //debug
2539
    if (packageSet != null)
2540
    {
2541
      for (int i = 0; i<packageSet.size(); i++)
2542
      {
2543
        MetaCatUtil.debugMessage("doctype in package set: " +
2544
                              (String)packageSet.elementAt(i), 34);
2545
      }
2546
    }//if
2547

    
2548
    // handle every accessionNumber
2549
    for (int i=0; i <docList.length; i++)
2550
    {
2551
      String accessionNumber = docList[i];
2552
      String owner = null;
2553
      String publicId = null;
2554
      // Get document owner and public id
2555
      try
2556
      {
2557
        owner = getFieldValueForDoc(accessionNumber, "user_owner");
2558
        publicId = getFieldValueForDoc(accessionNumber, "doctype");
2559
      }//try
2560
      catch (Exception e)
2561
      {
2562
        MetaCatUtil.debugMessage("Error in handleSetAccessAction: " +
2563
                                  e.getMessage(), 30);
2564
        error = "Error in set access control for document - " + accessionNumber+
2565
                 e.getMessage();
2566
        errorList.addElement(error);
2567
        continue;
2568
      }
2569
      //check if user is the owner. Only owner can do owner
2570
      if (username == null || owner == null || !username.equals(owner))
2571
      {
2572
        error = "User - " + username + " does not have permission to set " +
2573
                "access control for docid - " + accessionNumber;
2574
        errorList.addElement(error);
2575
        continue;
2576
      }
2577

    
2578
      // If docid publicid is BIN data file or other beta4, 6 package document
2579
      // we could not do set access control. Because we don't want inconsistent
2580
      // to its access docuemnt
2581
      if (publicId!=null && packageSet!=null && packageSet.contains(publicId))
2582
      {
2583
        error = "Could not set access control to document "+ accessionNumber +
2584
                "because it is in a pakcage and it has a access file for it";
2585
        errorList.addElement(error);
2586
        continue;
2587
      }
2588

    
2589
      // for every principle
2590
      for (int j = 0; j<principalList.length; j++)
2591
      {
2592
        String principal = principalList[j];
2593
        try
2594
        {
2595
          //insert permission
2596
          AccessControlForSingleFile accessControl = new
2597
                           AccessControlForSingleFile(accessionNumber,
2598
                                    principal, permission, permType, permOrder);
2599
          accessControl.insertPermissions();
2600
          success = "Set access control to document "+ accessionNumber +
2601
                    " successfully";
2602
          successList.addElement(success);
2603
        }
2604
        catch (Exception ee)
2605
        {
2606
          MetaCatUtil.debugMessage("Erorr in handleSetAccessAction2: " +
2607
                                   ee.getMessage(), 30);
2608
          error = "Faild to set access control for document " +
2609
                  accessionNumber + " because " + ee.getMessage();
2610
          errorList.addElement(error);
2611
          continue;
2612
        }
2613
      }//for every principle
2614
    }//for every document
2615
    outputResponse(successList, errorList, out);
2616
  }//handleSetAccessAction
2617

    
2618

    
2619
  /*
2620
   * A method try to determin a docid's public id, if couldn't find null
2621
   * will be returned.
2622
   */
2623
  private String getFieldValueForDoc(String accessionNumber, String fieldName)
2624
                                      throws Exception
2625
  {
2626
    if (accessionNumber==null || accessionNumber.equals("") ||fieldName == null
2627
        || fieldName.equals(""))
2628
    {
2629
      throw new Exception("Docid or field name was not specified");
2630
    }
2631

    
2632
    PreparedStatement pstmt = null;
2633
    ResultSet rs = null;
2634
    String fieldValue = null;
2635
    String docId = null;
2636
    DBConnection conn = null;
2637
    int serialNumber = -1;
2638

    
2639
    // get rid of revision if access number has
2640
    docId = MetaCatUtil.getDocIdFromString(accessionNumber);
2641
    try
2642
    {
2643
      //check out DBConnection
2644
      conn=DBConnectionPool.getDBConnection("MetaCatServlet.getPublicIdForDoc");
2645
      serialNumber=conn.getCheckOutSerialNumber();
2646
      pstmt = conn.prepareStatement(
2647
            "SELECT " + fieldName + " FROM xml_documents " +
2648
            "WHERE docid = ? ");
2649

    
2650
      pstmt.setString(1, docId);
2651
      pstmt.execute();
2652
      rs = pstmt.getResultSet();
2653
      boolean hasRow = rs.next();
2654
      int perm = 0;
2655
      if ( hasRow )
2656
      {
2657
        fieldValue = rs.getString(1);
2658
      }
2659
      else
2660
      {
2661
        throw new Exception("Could not find document: "+accessionNumber);
2662
      }
2663
    }//try
2664
    catch (Exception e)
2665
    {
2666
      MetaCatUtil.debugMessage("Exception in MetacatServlet.getPublicIdForDoc: "
2667
                               + e.getMessage(), 30);
2668
      throw e;
2669
    }
2670
    finally
2671
    {
2672
      try
2673
      {
2674
        rs.close();
2675
        pstmt.close();
2676

    
2677
      }
2678
      finally
2679
      {
2680
        DBConnectionPool.returnDBConnection(conn, serialNumber);
2681
      }
2682
    }
2683
    return fieldValue;
2684
  }//getFieldValueForDoc
2685

    
2686
  /*
2687
   * A method to output setAccess action result
2688
   */
2689
  private void outputResponse(Vector successList,
2690
                              Vector errorList,
2691
                              PrintWriter out)
2692
  {
2693
    boolean error = false;
2694
    boolean success = false;
2695
    // Output prolog
2696
    out.println(PROLOG);
2697
    // output success message
2698
    if ( successList != null)
2699
    {
2700
      for (int i = 0; i<successList.size(); i++)
2701
      {
2702
        out.println(SUCCESS);
2703
        out.println((String)successList.elementAt(i));
2704
        out.println(SUCCESSCLOSE);
2705
        success = true;
2706
      }//for
2707
    }//if
2708
    // output error message
2709
    if (errorList != null)
2710
    {
2711
      for (int i = 0; i<errorList.size(); i++)
2712
      {
2713
        out.println(ERROR);
2714
        out.println((String)errorList.elementAt(i));
2715
        out.println(ERRORCLOSE);
2716
        error = true;
2717
      }//for
2718
    }//if
2719

    
2720
    // if no error and no success info, send a error that nothing happened
2721
    if( !error && !success)
2722
    {
2723
      out.println(ERROR);
2724
      out.println("Nothing happend for setaccess action");
2725
      out.println(ERRORCLOSE);
2726
    }
2727

    
2728
  }//outputResponse
2729
}
(39-39/58)