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-31 11:45:56 -0800 (Wed, 31 Mar 2004) $'
11
 * '$Revision: 2080 $'
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
 * action=getaccesscontrol -- retrieve acl info for Metacat document<br>
97
 * action=getdoctypes -- retrieve all doctypes (publicID)<br>
98
 * action=getdtdschema -- retrieve a DTD or Schema file<br>
99
 * action=getdataguide -- retrieve a Data Guide<br>
100
 * action=getprincipals -- retrieve a list of principals in XML<br>
101
 * datadoc -- data document name (id)<br>
102
 * <p>
103
 * The particular combination of parameters that are valid for each
104
 * particular action value is quite specific.  This documentation
105
 * will be reorganized to reflect this information.
106
 */
107
public class MetaCatServlet extends HttpServlet {
108

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

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

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

    
156
      util = new MetaCatUtil();
157

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

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

    
170

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

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

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

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

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

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

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

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

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

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

    
232

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

    
239

    
240
      while (paramlist.hasMoreElements()) {
241

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

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

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

    
258

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

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

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

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

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

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

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

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

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

    
497
      //util.closeConnections();
498
      // Close the stream to the client
499
      //out.close();
500
    }
501
  }
502

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

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

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

    
545
      try {
546

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

    
552
      } catch(Exception e) {
553

    
554
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLoginAction: "
555
                                +e.getMessage(), 30);
556
      }
557

    
558
    // any output is returned
559
    }
560
  }
561

    
562
  /**
563
   * Handle the logout request. Close the connection.
564
   */
565
  private void handleLogoutAction(PrintWriter out, Hashtable params,
566
               HttpServletRequest request, HttpServletResponse response) {
567

    
568
    String qformat = ((String[])params.get("qformat"))[0];
569

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

    
583
    // produce output
584
    StringBuffer output = new StringBuffer();
585
    output.append("<?xml version=\"1.0\"?>");
586
    output.append("<logout>");
587
    output.append("User logged out");
588
    output.append("</logout>");
589

    
590
    //format and transform the output
591
    if (qformat.equals("xml")) {
592
      response.setContentType("text/xml");
593
      out.println(output.toString());
594
    } else {
595

    
596
      try {
597

    
598
        DBTransform trans = new DBTransform();
599
        response.setContentType("text/html");
600
        trans.transformXMLDocument(output.toString(), "-//NCEAS//login//EN",
601
                                   "-//W3C//HTML//EN", qformat, out, null);
602

    
603
      } catch(Exception e) {
604

    
605
        MetaCatUtil.debugMessage("Error in MetaCatServlet.handleLogoutAction"
606
                                  +e.getMessage(), 30);
607
      }
608
    }
609
  }
610
  // END OF LOGIN & LOGOUT SECTION
611

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

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

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

    
672
    resultdoc = createResultDocument(doclist, transformQuery(params));
673

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

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

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

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

    
741
    try
742
    {
743

    
744
      DBQuery queryobj = new DBQuery(saxparser);
745
      doclist = queryobj.findDocuments(new StringReader(xmlquery),user,groups);
746

    
747
      return doclist;
748
    }
749
    catch (Exception e)
750
    {
751

    
752
      MetaCatUtil.debugMessage("Error in MetacatServlet.runQuery: "
753
                                                      + e.getMessage(), 30);
754
      doclist = null;
755
      return doclist;
756
    }
757
  }
758

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

    
774
    try {
775

    
776
      DBTransform trans = new DBTransform();
777
      response.setContentType("text/html");
778
      trans.transformXMLDocument(resultdoc, "-//NCEAS//resultset//EN",
779
                                 "-//W3C//HTML//EN", qformat, out, params,
780
                                 sessionid);
781

    
782
    }
783
    catch(Exception e)
784
    {
785

    
786
      MetaCatUtil.debugMessage("Error in MetaCatServlet.transformResultset:"
787
                                +e.getMessage(), 30);
788
    }
789
  }
790

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

    
802
    // Print the resulting root nodes
803
    String docid = null;
804
    String document = null;
805
    resultset.append("<?xml version=\"1.0\"?>\n");
806
    resultset.append("<resultset>\n");
807

    
808
    resultset.append("  <query>" + xmlquery + "</query>");
809

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

    
821
    resultset.append("</resultset>");
822
    return resultset.toString();
823
  }
824
  // END OF SQUERY & QUERY SECTION
825

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

    
844
    String[] docs = new String[10];
845
    String docId = "";
846

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

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

    
913
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleExportAction: " +
914
                         e.getMessage(), 30);
915
      e.printStackTrace(System.out);
916

    
917
    }//catch
918

    
919
  }//handleExportAction
920

    
921

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

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

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

    
978
      }//else
979

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

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

    
1029
      MetaCatUtil.debugMessage("Error in MetacatServlet.handleReadInlineDataAction: "
1030
                                + e.getMessage(), 30);
1031

    
1032
    }//catch
1033

    
1034
  }//handleReadInlineDataAction
1035

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

    
1053
    try
1054
    {
1055
      //check out DBConnection
1056
      conn=DBConnectionPool.getDBConnection("AccessControlList.isAllowFirst");
1057
      serialNumber=conn.getCheckOutSerialNumber();
1058

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

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

    
1095

    
1096

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

    
1118
    try {
1119
      String[] docs = new String[0];
1120
      String docid = "";
1121
      String qformat = "";
1122
      String abstrpath = null;
1123

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

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

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

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

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

    
1186
      } /* end for */
1187

    
1188
      if ( zip ) {
1189
        zout.finish(); //terminate the zip file
1190
        zout.close();  //close the zip stream
1191
      }
1192

    
1193

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

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

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

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

    
1296
        }
1297
        // Close zip output stream
1298
        if ( zout != null ) { zout.close(); }
1299

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

    
1306
      }
1307

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

    
1313
  }
1314

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

    
1325
    try {
1326

    
1327

    
1328
      DocumentImpl doc = new DocumentImpl(docid);
1329

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

    
1336
        throw e;
1337
      }
1338

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

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

    
1358
        response.setContentType(contentType);
1359
        // if we decide to use "application/octet-stream" for all data returns
1360
        // response.setContentType("application/octet-stream");
1361

    
1362
        try {
1363

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

    
1375
      } else {
1376
        // this is metadata doc
1377
        if ( qformat.equals("xml") ) {
1378

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

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

    
1396
      }
1397
    }
1398
    catch (Exception except)
1399
    {
1400
      throw except;
1401

    
1402
    }
1403

    
1404
  }
1405

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

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

    
1451
  }
1452

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

    
1462
    try {
1463
      URL url = new URL(docid);
1464

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

    
1482
    } catch (MalformedURLException mue) {
1483

    
1484
      // this is metacat doc (data file or metadata doc)
1485

    
1486
      try {
1487

    
1488
        DocumentImpl doc = new DocumentImpl(docid);
1489

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

    
1496
          throw e;
1497
        }
1498

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

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

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

    
1535
      }
1536

    
1537
    }
1538

    
1539
  }
1540
  
1541
  /**
1542
   * If metacat couldn't find a data file or document locally, it will read this
1543
   * docid from its home server. This is for the replication feature
1544
   */
1545
  private void readFromRemoteMetaCat(HttpServletResponse response, String docid,
1546
                     String rev, String user, String password,
1547
                     ServletOutputStream out, boolean zip, ZipOutputStream zout)
1548
                        throws Exception
1549
 {
1550
   // Create a object of RemoteDocument, "" is for zipEntryPath
1551
   RemoteDocument remoteDoc =
1552
                        new RemoteDocument (docid, rev,user, password, "");
1553
   String docType = remoteDoc.getDocType();
1554
   // Only read data file
1555
   if (docType.equals("BIN"))
1556
   {
1557
    // If it is zip format
1558
    if (zip)
1559
    {
1560
      remoteDoc.readDocumentFromRemoteServerByZip(zout);
1561
    }//if
1562
    else
1563
    {
1564
      if (out == null)
1565
      {
1566
        out = response.getOutputStream();
1567
      }//if
1568
      response.setContentType("application/octet-stream");
1569
      remoteDoc.readDocumentFromRemoteServer(out);
1570
    }//else (not zip)
1571
   }//if doctype=bin
1572
   else
1573
   {
1574
     throw new Exception("Docid: "+docid+"."+rev+" couldn't find");
1575
   }//else
1576
 }//readFromRemoteMetaCat
1577

    
1578
  // END OF READ SECTION
1579

    
1580

    
1581

    
1582
  // INSERT/UPDATE SECTION
1583
  /**
1584
   * Handle the database putdocument request and write an XML document
1585
   * to the database connection
1586
   */
1587
  private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params,
1588
               String user, String[] groups) {
1589

    
1590
    DBConnection dbConn = null;
1591
    int serialNumber = -1;
1592

    
1593
    try {
1594
      // Get the document indicated
1595
      String[] doctext = (String[])params.get("doctext");
1596

    
1597
      String pub = null;
1598
      if (params.containsKey("public")) {
1599
        pub = ((String[])params.get("public"))[0];
1600
      }
1601

    
1602
      StringReader dtd = null;
1603
      if (params.containsKey("dtdtext")) {
1604
        String[] dtdtext = (String[])params.get("dtdtext");
1605
        try {
1606
          if ( !dtdtext[0].equals("") ) {
1607
            dtd = new StringReader(dtdtext[0]);
1608
          }
1609
        } catch (NullPointerException npe) {}
1610
      }
1611

    
1612
      StringReader xml = new StringReader(doctext[0]);
1613
      boolean validate = false;
1614
      DocumentImplWrapper documentWrapper = null;
1615
      try {
1616
        // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1617
        // in order to decide whether to use validation parser
1618
        validate = needDTDValidation(xml);
1619
        if (validate)
1620
        {
1621
          // set a dtd base validation parser
1622
          String rule = DocumentImpl.DTD;
1623
          documentWrapper = new DocumentImplWrapper(rule, validate);
1624
        }
1625
        else if (needSchemaValidation(xml))
1626
        {
1627
          // for eml2
1628
          if (needEml2Validation(xml))
1629
          {
1630
             // set eml2 base validation parser
1631
            String rule = DocumentImpl.EML2;
1632
            // using emlparser to check id validation
1633
            EMLParser parser = new EMLParser(doctext[0]);
1634
            documentWrapper = new DocumentImplWrapper(rule, true);
1635
          }
1636
          else
1637
          {
1638
            // set schema base validation parser
1639
            String rule = DocumentImpl.SCHEMA;
1640
            documentWrapper = new DocumentImplWrapper(rule, true);
1641
          }
1642
        }
1643
        else
1644
        {
1645
          documentWrapper = new DocumentImplWrapper("", false);
1646
        }
1647

    
1648
        String[] action = (String[])params.get("action");
1649
        String[] docid = (String[])params.get("docid");
1650
        String newdocid = null;
1651

    
1652
        String doAction = null;
1653
        if (action[0].equals("insert")) {
1654
          doAction = "INSERT";
1655
        } else if (action[0].equals("update")) {
1656
          doAction = "UPDATE";
1657
        }
1658

    
1659
        try
1660
        {
1661
          // get a connection from the pool
1662
          dbConn=DBConnectionPool.
1663
                  getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1664
          serialNumber=dbConn.getCheckOutSerialNumber();
1665

    
1666
           // write the document to the database
1667
          try
1668
          {
1669
            String accNumber = docid[0];
1670
            MetaCatUtil.debugMessage(""+ doAction + " " + accNumber +"...", 10);
1671
            if (accNumber.equals(""))
1672
            {
1673
              accNumber = null;
1674
            }//if
1675
            newdocid = documentWrapper.write(dbConn, xml, pub, dtd, doAction,
1676
                                          accNumber, user, groups);
1677

    
1678
          }//try
1679
          catch (NullPointerException npe)
1680
          {
1681
            newdocid = documentWrapper.write(dbConn, xml, pub, dtd, doAction,
1682
                                          null, user, groups);
1683
          }//catch
1684

    
1685
        }//try
1686
        finally
1687
        {
1688
          // Return db connection
1689
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1690
        }
1691

    
1692
        // set content type and other response header fields first
1693
        //response.setContentType("text/xml");
1694
        out.println("<?xml version=\"1.0\"?>");
1695
        out.println("<success>");
1696
        out.println("<docid>" + newdocid + "</docid>");
1697
        out.println("</success>");
1698

    
1699
      }
1700
      catch (NullPointerException npe)
1701
      {
1702
        //response.setContentType("text/xml");
1703
        out.println("<?xml version=\"1.0\"?>");
1704
        out.println("<error>");
1705
        out.println(npe.getMessage());
1706
        out.println("</error>");
1707
      }
1708
    }
1709
    catch (Exception e)
1710
    {
1711
      //response.setContentType("text/xml");
1712
      out.println("<?xml version=\"1.0\"?>");
1713
      out.println("<error>");
1714
      out.println(e.getMessage());
1715
      out.println("</error>");
1716
    }
1717
  }
1718

    
1719
  /**
1720
   * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1721
   * in order to decide whether to use validation parser
1722
   */
1723
  private static boolean needDTDValidation(StringReader xmlreader) throws 
1724
                                                             IOException 
1725
  {
1726

    
1727
    
1728
    StringBuffer cbuff = new StringBuffer();
1729
    java.util.Stack st = new java.util.Stack();
1730
    boolean validate = false;
1731
    int c;
1732
    int inx;
1733

    
1734
    // read from the stream until find the keywords
1735
    while ( (st.empty() || st.size()<4) && ((c = xmlreader.read()) != -1) ) {
1736
      cbuff.append((char)c);
1737

    
1738
      // "<!DOCTYPE" keyword is found; put it in the stack
1739
      if ( (inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1 ) {
1740
        cbuff = new StringBuffer();
1741
        st.push("<!DOCTYPE");
1742
      }
1743
      // "PUBLIC" keyword is found; put it in the stack
1744
      if ( (inx = cbuff.toString().indexOf("PUBLIC")) != -1 ) {
1745
        cbuff = new StringBuffer();
1746
        st.push("PUBLIC");
1747
      }
1748
      // "SYSTEM" keyword is found; put it in the stack
1749
      if ( (inx = cbuff.toString().indexOf("SYSTEM")) != -1 ) {
1750
        cbuff = new StringBuffer();
1751
        st.push("SYSTEM");
1752
      }
1753
      // ">" character is found; put it in the stack
1754
      // ">" is found twice: fisrt from <?xml ...?>
1755
      // and second from <!DOCTYPE ... >
1756
      if ( (inx = cbuff.toString().indexOf(">")) != -1 ) {
1757
        cbuff = new StringBuffer();
1758
        st.push(">");
1759
      }
1760
    }
1761

    
1762
    // close the stream
1763
    xmlreader.reset();
1764

    
1765
    // check the stack whether it contains the keywords:
1766
    // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1767
    if ( st.size() == 4 ) {
1768
      if ( ((String)st.pop()).equals(">") &&
1769
           ( ((String)st.peek()).equals("PUBLIC") |
1770
             ((String)st.pop()).equals("SYSTEM") ) &&
1771
           ((String)st.pop()).equals("<!DOCTYPE") )  {
1772
        validate = true;
1773
      }
1774
    }
1775

    
1776
    MetaCatUtil.debugMessage("Validation for dtd is " + validate, 10);
1777
    return validate;
1778
  }
1779
  // END OF INSERT/UPDATE SECTION
1780

    
1781
  /* check if the xml string contains key words to specify schema loocation*/
1782
  private boolean needSchemaValidation(StringReader xml) throws IOException
1783
  {
1784
    boolean needSchemaValidate =false;
1785
    if (xml == null)
1786
    {
1787
      MetaCatUtil.debugMessage("Validation for schema is " +
1788
                               needSchemaValidate, 10);
1789
      return needSchemaValidate;
1790
    }
1791
    System.out.println("before get target line");
1792
    String targetLine = getSchemaLine(xml);
1793
    System.out.println("before get target line");
1794
    // to see if the second line contain some keywords
1795
    if (targetLine != null && (targetLine.indexOf(SCHEMALOCATIONKEYWORD) != -1||
1796
             targetLine.indexOf(NONAMESPACELOCATION) != -1 ))
1797
    {
1798
      // if contains schema location key word, should be validate
1799
      needSchemaValidate = true;
1800
    }
1801

    
1802
    MetaCatUtil.debugMessage("Validation for schema is " +
1803
                             needSchemaValidate, 10);
1804
    return needSchemaValidate;
1805

    
1806
  }
1807

    
1808
   /* check if the xml string contains key words to specify schema loocation*/
1809
  private boolean needEml2Validation(StringReader xml) throws IOException
1810
  {
1811
    boolean needEml2Validate =false;
1812
    String emlNameSpace =DocumentImpl.EMLNAMESPACE;
1813
    String schemaLocationContent = null;
1814
    if (xml == null)
1815
    {
1816
      MetaCatUtil.debugMessage("Validation for schema is " +
1817
                               needEml2Validate, 10);
1818
      return needEml2Validate;
1819
    }
1820
    String targetLine = getSchemaLine(xml);
1821

    
1822
    if (targetLine != null)
1823
    {
1824
      
1825
      int startIndex = targetLine.indexOf(SCHEMALOCATIONKEYWORD);
1826
      int start = 1;
1827
      int end   = 1;
1828
      String schemaLocation = null;
1829
      int count = 0;
1830
      if (startIndex != -1)
1831
      {
1832
        for ( int i=startIndex; i<targetLine.length(); i++)
1833
        {
1834
          if (targetLine.charAt(i) =='"')
1835
          {
1836
            count ++;
1837
          }
1838
          if (targetLine.charAt(i) =='"' && count == 1)
1839
          {
1840
            start = i;
1841
          }
1842
          if (targetLine.charAt(i) =='"' && count == 2)
1843
          {
1844
            end = i;
1845
            break;
1846
          }
1847
        }
1848
      }
1849
      schemaLocation = targetLine.substring(start+1, end);
1850
      MetaCatUtil.debugMessage("schemaLocation in xml is: "+schemaLocation, 30);
1851
      if ( schemaLocation.indexOf(emlNameSpace) != -1)
1852
      {
1853
        needEml2Validate = true;
1854
      }
1855
    }
1856

    
1857
    MetaCatUtil.debugMessage("Validation for eml is " +
1858
                             needEml2Validate, 10);
1859
    return needEml2Validate;
1860

    
1861
  }
1862

    
1863
  private String getSchemaLine(StringReader xml) throws IOException
1864
  {
1865
    // find the line
1866
    String secondLine = null;
1867
    int count =0;
1868
    int endIndex = 0;
1869
    int startIndex = 0;
1870
    final int TARGETNUM = 2;
1871
    StringBuffer buffer = new StringBuffer();
1872
    boolean comment =false;
1873
    char thirdPreviousCharacter = '?';
1874
    char secondPreviousCharacter ='?';
1875
    char previousCharacter = '?';
1876
    char currentCharacter = '?';
1877
    
1878
    while ( (currentCharacter = (char) xml.read()) != -1)
1879
    {
1880
      //in a comment
1881
      if (currentCharacter =='-' && previousCharacter == '-'  && 
1882
          secondPreviousCharacter =='!' && thirdPreviousCharacter == '<')
1883
      {
1884
        comment = true;
1885
      }
1886
      //out of comment
1887
      if (comment && currentCharacter == '>' && previousCharacter == '-' && 
1888
          secondPreviousCharacter =='-')
1889
      {
1890
         comment = false;
1891
      }
1892
      
1893
      //this is not comment
1894
      if (currentCharacter !='!' && previousCharacter == '<' && !comment)
1895
      {
1896
        count ++;
1897
      }
1898
      // get target line
1899
      if (count == TARGETNUM && currentCharacter !='>')
1900
      {
1901
        buffer.append(currentCharacter);
1902
      }
1903
      if (count == TARGETNUM && currentCharacter == '>')
1904
      {
1905
          break;
1906
      }
1907
      thirdPreviousCharacter = secondPreviousCharacter;
1908
      secondPreviousCharacter = previousCharacter;
1909
      previousCharacter = currentCharacter;
1910
      
1911
    }
1912
    secondLine = buffer.toString();
1913
    MetaCatUtil.debugMessage("the second line string is: "+secondLine, 25);
1914
    xml.reset();
1915
    return secondLine;
1916
  }
1917

    
1918
  // DELETE SECTION
1919
  /**
1920
   * Handle the database delete request and delete an XML document
1921
   * from the database connection
1922
   */
1923
  private void handleDeleteAction(PrintWriter out, Hashtable params,
1924
               HttpServletResponse response, String user, String[] groups) {
1925

    
1926
    String[] docid = (String[])params.get("docid");
1927

    
1928
    // delete the document from the database
1929
    try {
1930

    
1931
                                      // NOTE -- NEED TO TEST HERE
1932
                                      // FOR EXISTENCE OF DOCID PARAM
1933
                                      // BEFORE ACCESSING ARRAY
1934
      try {
1935
        DocumentImpl.delete(docid[0], user, groups);
1936
        response.setContentType("text/xml");
1937
        out.println("<?xml version=\"1.0\"?>");
1938
        out.println("<success>");
1939
        out.println("Document deleted.");
1940
        out.println("</success>");
1941
      } catch (AccessionNumberException ane) {
1942
        response.setContentType("text/xml");
1943
        out.println("<?xml version=\"1.0\"?>");
1944
        out.println("<error>");
1945
        out.println("Error deleting document!!!");
1946
        out.println(ane.getMessage());
1947
        out.println("</error>");
1948
      }
1949
    } catch (Exception e) {
1950
      response.setContentType("text/xml");
1951
      out.println("<?xml version=\"1.0\"?>");
1952
      out.println("<error>");
1953
      out.println(e.getMessage());
1954
      out.println("</error>");
1955
    }
1956
  }
1957
  // END OF DELETE SECTION
1958

    
1959
  // VALIDATE SECTION
1960
  /**
1961
   * Handle the validation request and return the results to the requestor
1962
   */
1963
  private void handleValidateAction(PrintWriter out, Hashtable params) {
1964

    
1965
    // Get the document indicated
1966
    String valtext = null;
1967
    DBConnection dbConn = null;
1968
    int serialNumber = -1;
1969

    
1970
    try {
1971
      valtext = ((String[])params.get("valtext"))[0];
1972
    } catch (Exception nullpe) {
1973

    
1974

    
1975
      String docid = null;
1976
      try {
1977
        // Find the document id number
1978
        docid = ((String[])params.get("docid"))[0];
1979

    
1980

    
1981
        // Get the document indicated from the db
1982
        DocumentImpl xmldoc = new DocumentImpl(docid);
1983
        valtext = xmldoc.toString();
1984

    
1985
      } catch (NullPointerException npe) {
1986

    
1987
        out.println("<error>Error getting document ID: " + docid + "</error>");
1988
        //if ( conn != null ) { util.returnConnection(conn); }
1989
        return;
1990
      } catch (Exception e) {
1991

    
1992
        out.println(e.getMessage());
1993
      }
1994
    }
1995

    
1996

    
1997
    try {
1998
      // get a connection from the pool
1999
      dbConn=DBConnectionPool.
2000
                  getDBConnection("MetaCatServlet.handleValidateAction");
2001
      serialNumber=dbConn.getCheckOutSerialNumber();
2002
      DBValidate valobj = new DBValidate(saxparser,dbConn);
2003
      boolean valid = valobj.validateString(valtext);
2004

    
2005
      // set content type and other response header fields first
2006

    
2007
      out.println(valobj.returnErrors());
2008

    
2009
    } catch (NullPointerException npe2) {
2010
      // set content type and other response header fields first
2011

    
2012
      out.println("<error>Error validating document.</error>");
2013
    } catch (Exception e) {
2014

    
2015
      out.println(e.getMessage());
2016
    } finally {
2017
      // Return db connection
2018
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2019
    }
2020
  }
2021
  // END OF VALIDATE SECTION
2022

    
2023
  // OTHER ACTION HANDLERS
2024

    
2025
  /**
2026
   * Handle "getrevsionanddoctype" action
2027
   * Given a docid, return it's current revision and doctype from data base
2028
   * The output is String look like "rev;doctype"
2029
   */
2030
  private void handleGetRevisionAndDocTypeAction(PrintWriter out,
2031
                                                              Hashtable params)
2032
  {
2033
    // To store doc parameter
2034
    String [] docs = new String[10];
2035
    // Store a single doc id
2036
    String givenDocId = null;
2037
    // Get docid from parameters
2038
    if (params.containsKey("docid"))
2039
    {
2040
      docs = (String[])params.get("docid");
2041
    }
2042
    // Get first docid form string array
2043
    givenDocId = docs[0];
2044

    
2045
    try
2046
    {
2047
      // Make sure there is a docid
2048
      if (givenDocId == null || givenDocId.equals(""))
2049
      {
2050
        throw new Exception("User didn't specify docid!");
2051
      }//if
2052

    
2053
      // Create a DBUtil object
2054
      DBUtil dbutil = new DBUtil();
2055
      // Get a rev and doctype
2056
      String revAndDocType =
2057
                dbutil.getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
2058
      out.println(revAndDocType);
2059

    
2060
    }//try
2061
    catch (Exception e)
2062
    {
2063
      // Handle exception
2064
      out.println("<?xml version=\"1.0\"?>");
2065
      out.println("<error>");
2066
      out.println(e.getMessage());
2067
      out.println("</error>");
2068
    }//catch
2069

    
2070
  }//handleGetRevisionAndDocTypeAction
2071

    
2072
  /**
2073
   * Handle "getaccesscontrol" action.
2074
   * Read Access Control List from db connection in XML format
2075
   */
2076
  private void handleGetAccessControlAction(PrintWriter out, Hashtable params,
2077
                                       HttpServletResponse response,
2078
                                       String username, String[] groupnames) {
2079

    
2080
    DBConnection dbConn = null;
2081
    int serialNumber = -1;
2082
    String docid = ((String[])params.get("docid"))[0];
2083

    
2084
    try {
2085

    
2086
        // get connection from the pool
2087
        dbConn=DBConnectionPool.
2088
                 getDBConnection("MetaCatServlet.handleGetAccessControlAction");
2089
        serialNumber=dbConn.getCheckOutSerialNumber();
2090
        AccessControlList aclobj = new AccessControlList(dbConn);
2091
        String acltext = aclobj.getACL(docid, username, groupnames);
2092
        out.println(acltext);
2093

    
2094
    } catch (Exception e) {
2095
      out.println("<?xml version=\"1.0\"?>");
2096
      out.println("<error>");
2097
      out.println(e.getMessage());
2098
      out.println("</error>");
2099
    } finally {
2100
      // Retrun db connection to pool
2101
      DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2102
    }
2103

    
2104
  }
2105

    
2106
  /**
2107
   * Handle the "getprincipals" action.
2108
   * Read all principals from authentication scheme in XML format
2109
   */
2110
  private void handleGetPrincipalsAction(PrintWriter out, String user,
2111
                                         String password) {
2112

    
2113

    
2114
    try {
2115

    
2116

    
2117
        AuthSession auth = new AuthSession();
2118
        String principals = auth.getPrincipals(user, password);
2119
        out.println(principals);
2120

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

    
2128
  }
2129

    
2130
  /**
2131
   * Handle "getdoctypes" action.
2132
   * Read all doctypes from db connection in XML format
2133
   */
2134
  private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
2135
                                       HttpServletResponse response) {
2136

    
2137

    
2138
    try {
2139

    
2140

    
2141
        DBUtil dbutil = new DBUtil();
2142
        String doctypes = dbutil.readDoctypes();
2143
        out.println(doctypes);
2144

    
2145
    } catch (Exception e) {
2146
      out.println("<?xml version=\"1.0\"?>");
2147
      out.println("<error>");
2148
      out.println(e.getMessage());
2149
      out.println("</error>");
2150
    }
2151

    
2152
  }
2153

    
2154
  /**
2155
   * Handle the "getdtdschema" action.
2156
   * Read DTD or Schema file for a given doctype from Metacat catalog system
2157
   */
2158
  private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
2159
                                        HttpServletResponse response) {
2160

    
2161

    
2162
    String doctype = null;
2163
    String[] doctypeArr = (String[])params.get("doctype");
2164

    
2165
    // get only the first doctype specified in the list of doctypes
2166
    // it could be done for all doctypes in that list
2167
    if (doctypeArr != null) {
2168
        doctype = ((String[])params.get("doctype"))[0];
2169
    }
2170

    
2171
    try {
2172

    
2173

    
2174
        DBUtil dbutil = new DBUtil();
2175
        String dtdschema = dbutil.readDTDSchema(doctype);
2176
        out.println(dtdschema);
2177

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

    
2185
  }
2186

    
2187
  /**
2188
   * Handle the "getlastdocid" action.
2189
   * Get the latest docid with rev number from db connection in XML format
2190
   */
2191
  private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
2192
                                        HttpServletResponse response) {
2193

    
2194

    
2195
    String scope = ((String[])params.get("scope"))[0];
2196
    if (scope == null) {
2197
        scope = ((String[])params.get("username"))[0];
2198
    }
2199

    
2200
    try {
2201

    
2202

    
2203
        DBUtil dbutil = new DBUtil();
2204
        String lastDocid = dbutil.getMaxDocid(scope);
2205
        out.println("<?xml version=\"1.0\"?>");
2206
        out.println("<lastDocid>");
2207
        out.println("  <scope>" + scope + "</scope>");
2208
        out.println("  <docid>" + lastDocid + "</docid>");
2209
        out.println("</lastDocid>");
2210

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

    
2218
  }
2219

    
2220
  /**
2221
   * Handle documents passed to metacat that are encoded using the
2222
   * "multipart/form-data" mime type.  This is typically used for uploading
2223
   * data files which may be binary and large.
2224
   */
2225
  private void handleMultipartForm(HttpServletRequest request,
2226
                                   HttpServletResponse response)
2227
  {
2228
    PrintWriter out = null;
2229
    String action = null;
2230

    
2231
    // Parse the multipart form, and save the parameters in a Hashtable and
2232
    // save the FileParts in a hashtable
2233

    
2234
    Hashtable params = new Hashtable();
2235
    Hashtable fileList = new Hashtable();
2236
    int sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit")))
2237
                                                                   .intValue();
2238
    MetaCatUtil.debugMessage("The limit size of data file is: "+sizeLimit, 50);
2239

    
2240
    try {
2241
      // MBJ: need to put filesize limit in Metacat config (metacat.properties)
2242
      MultipartParser mp = new MultipartParser(request, sizeLimit*1024*1024);
2243
      Part part;
2244
      while ((part = mp.readNextPart()) != null) {
2245
        String name = part.getName();
2246

    
2247
        if (part.isParam()) {
2248
          // it's a parameter part
2249
          ParamPart paramPart = (ParamPart) part;
2250
          String value = paramPart.getStringValue();
2251
          params.put(name, value);
2252
          if (name.equals("action")) {
2253
            action = value;
2254
          }
2255
        } else if (part.isFile()) {
2256
          // it's a file part
2257
          FilePart filePart = (FilePart) part;
2258
          fileList.put(name, filePart);
2259

    
2260
          // Stop once the first file part is found, otherwise going onto the
2261
          // next part prevents access to the file contents.  So...for upload
2262
          // to work, the datafile must be the last part
2263
          break;
2264
        }
2265
      }
2266
    } catch (IOException ioe) {
2267
      try {
2268
        out = response.getWriter();
2269
      } catch (IOException ioe2) {
2270
        System.err.println("Fatal Error: couldn't get response output stream.");
2271
      }
2272
      out.println("<?xml version=\"1.0\"?>");
2273
      out.println("<error>");
2274
      out.println("Error: problem reading multipart data.");
2275
      out.println("</error>");
2276
    }
2277

    
2278
    // Get the session information
2279
    String username = null;
2280
    String password = null;
2281
    String[] groupnames = null;
2282
    String sess_id = null;
2283

    
2284
    // be aware of session expiration on every request
2285
    HttpSession sess = request.getSession(true);
2286
    if (sess.isNew()) {
2287
      // session expired or has not been stored b/w user requests
2288
      username = "public";
2289
      sess.setAttribute("username", username);
2290
    } else {
2291
      username = (String)sess.getAttribute("username");
2292
      password = (String)sess.getAttribute("password");
2293
      groupnames = (String[])sess.getAttribute("groupnames");
2294
      try {
2295
        sess_id = (String)sess.getId();
2296
      } catch(IllegalStateException ise) {
2297
        System.out.println("error in  handleMultipartForm: this shouldn't " +
2298
                           "happen: the session should be valid: " +
2299
                           ise.getMessage());
2300
      }
2301
    }
2302

    
2303
    // Get the out stream
2304
    try {
2305
          out = response.getWriter();
2306
        } catch (IOException ioe2) {
2307
          util.debugMessage("Fatal Error: couldn't get response "+
2308
                             "output stream.", 30);
2309
        }
2310

    
2311
    if ( action.equals("upload")) {
2312
      if (username != null &&  !username.equals("public")) {
2313
        handleUploadAction(request, out, params, fileList,
2314
                           username, groupnames);
2315
      } else {
2316

    
2317
        out.println("<?xml version=\"1.0\"?>");
2318
        out.println("<error>");
2319
        out.println("Permission denied for " + action);
2320
        out.println("</error>");
2321
      }
2322
    } else {
2323
      /*try {
2324
        out = response.getWriter();
2325
      } catch (IOException ioe2) {
2326
        System.err.println("Fatal Error: couldn't get response output stream.");
2327
      }*/
2328
      out.println("<?xml version=\"1.0\"?>");
2329
      out.println("<error>");
2330
      out.println("Error: action not registered.  Please report this error.");
2331
      out.println("</error>");
2332
    }
2333
    out.close();
2334
  }
2335

    
2336
  /**
2337
   * Handle the upload action by saving the attached file to disk and
2338
   * registering it in the Metacat db
2339
   */
2340
  private void handleUploadAction(HttpServletRequest request,
2341
                                  PrintWriter out,
2342
                                  Hashtable params, Hashtable fileList,
2343
                                  String username, String[] groupnames)
2344
  {
2345
    //PrintWriter out = null;
2346
    //Connection conn = null;
2347
    String action = null;
2348
    String docid = null;
2349

    
2350
    /*response.setContentType("text/xml");
2351
    try
2352
    {
2353
      out = response.getWriter();
2354
    }
2355
    catch (IOException ioe2)
2356
    {
2357
      System.err.println("Fatal Error: couldn't get response output stream.");
2358
    }*/
2359

    
2360
    if (params.containsKey("docid"))
2361
    {
2362
      docid = (String)params.get("docid");
2363
    }
2364

    
2365
    // Make sure we have a docid and datafile
2366
    if (docid != null && fileList.containsKey("datafile")) {
2367

    
2368
      // Get a reference to the file part of the form
2369
      FilePart filePart = (FilePart)fileList.get("datafile");
2370
      String fileName = filePart.getFileName();
2371
      MetaCatUtil.debugMessage("Uploading filename: " + fileName, 10);
2372

    
2373
      // Check if the right file existed in the uploaded data
2374
      if (fileName != null) {
2375

    
2376
        try
2377
        {
2378
           //MetaCatUtil.debugMessage("Upload datafile " + docid +"...", 10);
2379
           //If document get lock data file grant
2380
           if (DocumentImpl.getDataFileLockGrant(docid))
2381
           {
2382
              // register the file in the database (which generates an exception
2383
              //if the docid is not acceptable or other untoward things happen
2384
              DocumentImpl.registerDocument(fileName, "BIN", docid, username);
2385

    
2386
              // Save the data file to disk using "docid" as the name
2387
              dataDirectory.mkdirs();
2388
              File newFile = new File(dataDirectory, docid);
2389
              long size = filePart.writeTo(newFile);
2390

    
2391
              // Force replication this data file
2392
              // To data file, "insert" and update is same
2393
              // The fourth parameter is null. Because it is notification server
2394
              // and this method is in MetaCatServerlet. It is original command,
2395
              // not get force replication info from another metacat
2396
              ForceReplicationHandler frh = new ForceReplicationHandler
2397
                                                (docid, "insert", false, null);
2398

    
2399
              // set content type and other response header fields first
2400
              out.println("<?xml version=\"1.0\"?>");
2401
              out.println("<success>");
2402
              out.println("<docid>" + docid + "</docid>");
2403
              out.println("<size>" + size + "</size>");
2404
              out.println("</success>");
2405
          }//if
2406

    
2407
        } //try
2408
        catch (Exception e)
2409
        {
2410
          out.println("<?xml version=\"1.0\"?>");
2411
          out.println("<error>");
2412
          out.println(e.getMessage());
2413
          out.println("</error>");
2414
        }
2415

    
2416
      }
2417
      else
2418
      {
2419
        // the field did not contain a file
2420
        out.println("<?xml version=\"1.0\"?>");
2421
        out.println("<error>");
2422
        out.println("The uploaded data did not contain a valid file.");
2423
        out.println("</error>");
2424
      }
2425
    }
2426
    else
2427
    {
2428
      // Error bcse docid missing or file missing
2429
      out.println("<?xml version=\"1.0\"?>");
2430
      out.println("<error>");
2431
      out.println("The uploaded data did not contain a valid docid " +
2432
                  "or valid file.");
2433
      out.println("</error>");
2434
    }
2435
  }
2436

    
2437
  /*
2438
   * A method to handle set access action
2439
   */
2440
  private void handleSetAccessAction(PrintWriter out,
2441
                                   Hashtable params,
2442
                                   String username)
2443
  {
2444
    String [] docList        = null;
2445
    String [] principalList  = null;
2446
    String [] permissionList = null;
2447
    String [] permTypeList   = null;
2448
    String [] permOrderList  = null;
2449
    String permission = null;
2450
    String permType   = null;
2451
    String permOrder  = null;
2452
    Vector errorList  = new Vector();
2453
    String error      = null;
2454
    Vector successList = new Vector();
2455
    String success    = null;
2456

    
2457

    
2458
    // Get parameters
2459
    if (params.containsKey("docid"))
2460
    {
2461
      docList = (String[])params.get("docid");
2462
    }
2463
    if (params.containsKey("principal"))
2464
    {
2465
      principalList = (String[])params.get("principal");
2466
    }
2467
    if (params.containsKey("permission"))
2468
    {
2469
      permissionList = (String[])params.get("permission");
2470

    
2471
    }
2472
    if (params.containsKey("permType"))
2473
    {
2474
      permTypeList = (String[])params.get("permType");
2475

    
2476
    }
2477
    if (params.containsKey("permOrder"))
2478
    {
2479
      permOrderList = (String[])params.get("permOrder");
2480

    
2481
    }
2482

    
2483
    // Make sure the parameter is not null
2484
    if (docList == null || principalList == null || permTypeList == null ||
2485
        permissionList == null)
2486
    {
2487
      error = "Please check your parameter list, it should look like: "+
2488
              "?action=setaccess&docid=pipeline.1.1&principal=public" +
2489
              "&permission=read&permType=allow&permOrder=allowFirst";
2490
      errorList.addElement(error);
2491
      outputResponse(successList, errorList, out);
2492
      return;
2493
    }
2494

    
2495
    // Only select first element for permission, type and order
2496
    permission = permissionList[0];
2497
    permType = permTypeList[0];
2498
    if (permOrderList != null)
2499
    {
2500
       permOrder = permOrderList[0];
2501
    }
2502

    
2503
    // Get package doctype set
2504
    Vector packageSet =MetaCatUtil.getOptionList(
2505
                                    MetaCatUtil.getOption("packagedoctypeset"));
2506
    //debug
2507
    if (packageSet != null)
2508
    {
2509
      for (int i = 0; i<packageSet.size(); i++)
2510
      {
2511
        MetaCatUtil.debugMessage("doctype in package set: " +
2512
                              (String)packageSet.elementAt(i), 34);
2513
      }
2514
    }//if
2515

    
2516
    // handle every accessionNumber
2517
    for (int i=0; i <docList.length; i++)
2518
    {
2519
      String accessionNumber = docList[i];
2520
      String owner = null;
2521
      String publicId = null;
2522
      // Get document owner and public id
2523
      try
2524
      {
2525
        owner = getFieldValueForDoc(accessionNumber, "user_owner");
2526
        publicId = getFieldValueForDoc(accessionNumber, "doctype");
2527
      }//try
2528
      catch (Exception e)
2529
      {
2530
        MetaCatUtil.debugMessage("Error in handleSetAccessAction: " +
2531
                                  e.getMessage(), 30);
2532
        error = "Error in set access control for document - " + accessionNumber+
2533
                 e.getMessage();
2534
        errorList.addElement(error);
2535
        continue;
2536
      }
2537
      //check if user is the owner. Only owner can do owner
2538
      if (username == null || owner == null || !username.equals(owner))
2539
      {
2540
        error = "User - " + username + " does not have permission to set " +
2541
                "access control for docid - " + accessionNumber;
2542
        errorList.addElement(error);
2543
        continue;
2544
      }
2545

    
2546
      // If docid publicid is BIN data file or other beta4, 6 package document
2547
      // we could not do set access control. Because we don't want inconsistent
2548
      // to its access docuemnt
2549
      if (publicId!=null && packageSet!=null && packageSet.contains(publicId))
2550
      {
2551
        error = "Could not set access control to document "+ accessionNumber +
2552
                "because it is in a pakcage and it has a access file for it";
2553
        errorList.addElement(error);
2554
        continue;
2555
      }
2556

    
2557
      // for every principle
2558
      for (int j = 0; j<principalList.length; j++)
2559
      {
2560
        String principal = principalList[j];
2561
        try
2562
        {
2563
          //insert permission
2564
          AccessControlForSingleFile accessControl = new
2565
                           AccessControlForSingleFile(accessionNumber,
2566
                                    principal, permission, permType, permOrder);
2567
          accessControl.insertPermissions();
2568
          success = "Set access control to document "+ accessionNumber +
2569
                    " successfully";
2570
          successList.addElement(success);
2571
        }
2572
        catch (Exception ee)
2573
        {
2574
          MetaCatUtil.debugMessage("Erorr in handleSetAccessAction2: " +
2575
                                   ee.getMessage(), 30);
2576
          error = "Faild to set access control for document " +
2577
                  accessionNumber + " because " + ee.getMessage();
2578
          errorList.addElement(error);
2579
          continue;
2580
        }
2581
      }//for every principle
2582
    }//for every document
2583
    outputResponse(successList, errorList, out);
2584
  }//handleSetAccessAction
2585

    
2586

    
2587
  /*
2588
   * A method try to determin a docid's public id, if couldn't find null
2589
   * will be returned.
2590
   */
2591
  private String getFieldValueForDoc(String accessionNumber, String fieldName)
2592
                                      throws Exception
2593
  {
2594
    if (accessionNumber==null || accessionNumber.equals("") ||fieldName == null
2595
        || fieldName.equals(""))
2596
    {
2597
      throw new Exception("Docid or field name was not specified");
2598
    }
2599

    
2600
    PreparedStatement pstmt = null;
2601
    ResultSet rs = null;
2602
    String fieldValue = null;
2603
    String docId = null;
2604
    DBConnection conn = null;
2605
    int serialNumber = -1;
2606

    
2607
    // get rid of revision if access number has
2608
    docId = MetaCatUtil.getDocIdFromString(accessionNumber);
2609
    try
2610
    {
2611
      //check out DBConnection
2612
      conn=DBConnectionPool.getDBConnection("MetaCatServlet.getPublicIdForDoc");
2613
      serialNumber=conn.getCheckOutSerialNumber();
2614
      pstmt = conn.prepareStatement(
2615
            "SELECT " + fieldName + " FROM xml_documents " +
2616
            "WHERE docid = ? ");
2617

    
2618
      pstmt.setString(1, docId);
2619
      pstmt.execute();
2620
      rs = pstmt.getResultSet();
2621
      boolean hasRow = rs.next();
2622
      int perm = 0;
2623
      if ( hasRow )
2624
      {
2625
        fieldValue = rs.getString(1);
2626
      }
2627
      else
2628
      {
2629
        throw new Exception("Could not find document: "+accessionNumber);
2630
      }
2631
    }//try
2632
    catch (Exception e)
2633
    {
2634
      MetaCatUtil.debugMessage("Exception in MetacatServlet.getPublicIdForDoc: "
2635
                               + e.getMessage(), 30);
2636
      throw e;
2637
    }
2638
    finally
2639
    {
2640
      try
2641
      {
2642
        rs.close();
2643
        pstmt.close();
2644

    
2645
      }
2646
      finally
2647
      {
2648
        DBConnectionPool.returnDBConnection(conn, serialNumber);
2649
      }
2650
    }
2651
    return fieldValue;
2652
  }//getFieldValueForDoc
2653

    
2654
  /*
2655
   * A method to output setAccess action result
2656
   */
2657
  private void outputResponse(Vector successList,
2658
                              Vector errorList,
2659
                              PrintWriter out)
2660
  {
2661
    boolean error = false;
2662
    boolean success = false;
2663
    // Output prolog
2664
    out.println(PROLOG);
2665
    // output success message
2666
    if ( successList != null)
2667
    {
2668
      for (int i = 0; i<successList.size(); i++)
2669
      {
2670
        out.println(SUCCESS);
2671
        out.println((String)successList.elementAt(i));
2672
        out.println(SUCCESSCLOSE);
2673
        success = true;
2674
      }//for
2675
    }//if
2676
    // output error message
2677
    if (errorList != null)
2678
    {
2679
      for (int i = 0; i<errorList.size(); i++)
2680
      {
2681
        out.println(ERROR);
2682
        out.println((String)errorList.elementAt(i));
2683
        out.println(ERRORCLOSE);
2684
        error = true;
2685
      }//for
2686
    }//if
2687

    
2688
    // if no error and no success info, send a error that nothing happened
2689
    if( !error && !success)
2690
    {
2691
      out.println(ERROR);
2692
      out.println("Nothing happend for setaccess action");
2693
      out.println(ERRORCLOSE);
2694
    }
2695

    
2696
  }//outputResponse
2697
}
(39-39/59)