Project

General

Profile

1 51 jones
/**
2 203 jones
 *  '$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 361 berkley
 *    Authors: Matt Jones, Dan Higgins, Jivka Bojilova, Chad Berkley
7 348 jones
 *    Release: @release@
8 154 jones
 *
9 203 jones
 *   '$Author$'
10
 *     '$Date$'
11
 * '$Revision$'
12 669 jones
 *
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 51 jones
 */
27
28
package edu.ucsb.nceas.metacat;
29
30 798 jones
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 733 bojilova
import java.io.File;
36 46 jones
import java.io.PrintWriter;
37
import java.io.IOException;
38 50 jones
import java.io.StringReader;
39 185 jones
import java.io.FileInputStream;
40 731 bojilova
import java.io.BufferedInputStream;
41 46 jones
import java.util.Enumeration;
42
import java.util.Hashtable;
43 341 berkley
import java.util.ResourceBundle;
44 648 berkley
import java.util.Random;
45 82 jones
import java.util.PropertyResourceBundle;
46 50 jones
import java.net.URL;
47
import java.net.MalformedURLException;
48 85 jones
import java.sql.PreparedStatement;
49
import java.sql.ResultSet;
50 50 jones
import java.sql.Connection;
51 55 jones
import java.sql.SQLException;
52 361 berkley
import java.lang.reflect.*;
53 453 berkley
import java.net.*;
54 458 berkley
import java.util.zip.*;
55 46 jones
56
import javax.servlet.ServletConfig;
57
import javax.servlet.ServletContext;
58
import javax.servlet.ServletException;
59 48 jones
import javax.servlet.ServletInputStream;
60 46 jones
import javax.servlet.http.HttpServlet;
61
import javax.servlet.http.HttpServletRequest;
62
import javax.servlet.http.HttpServletResponse;
63 210 bojilova
import javax.servlet.http.HttpSession;
64 47 jones
import javax.servlet.http.HttpUtils;
65 458 berkley
import javax.servlet.ServletOutputStream;
66 46 jones
67 204 jones
import org.xml.sax.SAXException;
68
69 46 jones
/**
70
 * A metadata catalog server implemented as a Java Servlet
71 154 jones
 *
72
 * <p>Valid parameters are:<br>
73
 * action=query -- query the values of all elements and attributes
74
 *                     and return a result set of nodes<br>
75 943 tao
 * action=squery -- structured query (see pathquery.dtd)<br>
76
 * action= -- export a zip format for data packadge<br>
77 731 bojilova
 * action=read -- read any metadata/data file from Metacat and from Internet<br>
78 205 jones
 * action=insert -- insert an XML document into the database store<br>
79
 * action=update -- update an XML document that is in the database store<br>
80
 * action=delete --  delete an XML document from the database store<br>
81
 * action=validate -- vallidate the xml contained in valtext<br>
82
 * doctype -- document type list returned by the query (publicID)<br>
83 154 jones
 * qformat=xml -- display resultset from query in XML<br>
84
 * qformat=html -- display resultset from query in HTML<br>
85 731 bojilova
 * qformat=zip -- zip resultset from query<br>
86 154 jones
 * docid=34 -- display the document with the document ID number 34<br>
87 205 jones
 * doctext -- XML text of the document to load into the database<br>
88 598 bojilova
 * acltext -- XML access text for a document to load into the database<br>
89
 * dtdtext -- XML DTD text for a new DTD to load into Metacat XML Catalog<br>
90 183 jones
 * query -- actual query text (to go with 'action=query' or 'action=squery')<br>
91 205 jones
 * valtext -- XML text to be validated<br>
92 731 bojilova
 * abstractpath -- XPath in metadata document to read from<br>
93 688 bojilova
 * action=getaccesscontrol -- retrieve acl info for Metacat document<br>
94
 * action=getdoctypes -- retrieve all doctypes (publicID)<br>
95 699 bojilova
 * action=getdtdschema -- retrieve a DTD or Schema file<br>
96 688 bojilova
 * action=getdataguide -- retrieve a Data Guide<br>
97 725 bojilova
 * action=getprincipals -- retrieve a list of principals in XML<br>
98 205 jones
 * datadoc -- data document name (id)<br>
99
 * <p>
100
 * The particular combination of parameters that are valid for each
101
 * particular action value is quite specific.  This documentation
102
 * will be reorganized to reflect this information.
103 46 jones
 */
104
public class MetaCatServlet extends HttpServlet {
105
106 370 berkley
  private ServletConfig config = null;
107
  private ServletContext context = null;
108
  private Hashtable connectionPool = new Hashtable();
109
  private String resultStyleURL = null;
110
  private String xmlcatalogfile = null;
111
  private String saxparser = null;
112 798 jones
  private String datafilepath = null;
113
  private File dataDirectory = null;
114 370 berkley
  private String servletpath = null;
115 822 jones
  private String htmlpath = null;
116 380 jones
  private PropertyResourceBundle options = null;
117
  private MetaCatUtil util = null;
118
119 50 jones
  /**
120
   * Initialize the servlet by creating appropriate database connections
121
   */
122 46 jones
  public void init( ServletConfig config ) throws ServletException {
123
    try {
124
      super.init( config );
125
      this.config = config;
126 332 bojilova
      this.context = config.getServletContext();
127 184 jones
      System.out.println("MetaCatServlet Initialize");
128 82 jones
129 184 jones
      util = new MetaCatUtil();
130
131 83 jones
      // Get the configuration file information
132 184 jones
      resultStyleURL = util.getOption("resultStyleURL");
133
      xmlcatalogfile = util.getOption("xmlcatalogfile");
134
      saxparser = util.getOption("saxparser");
135 798 jones
      datafilepath = util.getOption("datafilepath");
136
      dataDirectory = new File(datafilepath);
137 360 bojilova
      servletpath = util.getOption("servletpath");
138
      htmlpath = util.getOption("htmlpath");
139 598 bojilova
140 731 bojilova
// MOVED IT TO doGet() & doPost()
141 598 bojilova
//      try {
142
//        // Open a pool of db connections
143
//        connectionPool = util.getConnectionPool();
144
//      } catch (Exception e) {
145
//        System.err.println("Error creating pool of database connections");
146
//        System.err.println(e.getMessage());
147
//      }
148 46 jones
    } catch ( ServletException ex ) {
149
      throw ex;
150
    }
151
  }
152
153 320 bojilova
  /**
154
   * Close all db connections from the pool
155
   */
156
  public void destroy() {
157
158
    if (util != null) {
159
        util.closeConnections();
160
    }
161
  }
162
163 50 jones
  /** Handle "GET" method requests from HTTP clients */
164 46 jones
  public void doGet (HttpServletRequest request, HttpServletResponse response)
165
    throws ServletException, IOException {
166
167 48 jones
    // Process the data and send back the response
168 59 jones
    handleGetOrPost(request, response);
169 48 jones
  }
170
171 50 jones
  /** Handle "POST" method requests from HTTP clients */
172 48 jones
  public void doPost( HttpServletRequest request, HttpServletResponse response)
173
    throws ServletException, IOException {
174
175
    // Process the data and send back the response
176 59 jones
    handleGetOrPost(request, response);
177 48 jones
  }
178
179 49 jones
  /**
180 50 jones
   * Control servlet response depending on the action parameter specified
181 49 jones
   */
182 382 berkley
  private void handleGetOrPost(HttpServletRequest request,
183 798 jones
                               HttpServletResponse response)
184
                               throws ServletException, IOException
185
  {
186 48 jones
187 309 bojilova
    if ( util == null ) {
188
        util = new MetaCatUtil();
189
    }
190 598 bojilova
    if ( connectionPool.isEmpty() ) {
191 309 bojilova
      try {
192
        // Open a pool of db connections
193
        connectionPool = util.getConnectionPool();
194
      } catch (Exception e) {
195 675 berkley
        System.err.println("Error creating pool of database connections in " +
196
                            " MetaCatServlet.handleGetOrPost");
197 309 bojilova
        System.err.println(e.getMessage());
198
      }
199
    }
200 49 jones
    // Get a handle to the output stream back to the client
201 566 jones
    //PrintWriter pwout = response.getWriter();
202 102 jones
    //response.setContentType("text/html");
203 798 jones
204
    // Deal with forms that are encoded as "multipart/form-data" differently
205
    // this is mainly used for uploading non-xml files using that may be binary
206 800 jones
    String ctype = request.getContentType();
207
    if (ctype != null && ctype.startsWith("multipart/form-data")) {
208 798 jones
      handleMultipartForm(request, response);
209
    } else {
210 943 tao
211 49 jones
212 798 jones
      String name = null;
213
      String[] value = null;
214
      String[] docid = new String[3];
215
      Hashtable params = new Hashtable();
216
      Enumeration paramlist = request.getParameterNames();
217
      while (paramlist.hasMoreElements()) {
218
        name = (String)paramlist.nextElement();
219
        value = request.getParameterValues(name);
220
221
        // Decode the docid and mouse click information
222
        if (name.endsWith(".y")) {
223
          docid[0] = name.substring(0,name.length()-2);
224
          params.put("docid", docid);
225
          name = "ypos";
226 648 berkley
        }
227 798 jones
        if (name.endsWith(".x")) {
228
          name = "xpos";
229
        }
230
231
        params.put(name,value);
232 425 bojilova
      }
233 798 jones
234
      //if the user clicked on the input images, decode which image
235
      //was clicked then set the action.
236
      String action = ((String[])params.get("action"))[0];
237
      util.debugMessage("Line 213: Action is: " + action);
238
239
      // This block handles session management for the servlet
240
      // by looking up the current session information for all actions
241
      // other than "login" and "logout"
242
      String username = null;
243
      String password = null;
244 802 bojilova
      String[] groupnames = null;
245 798 jones
      String sess_id = null;
246
247
      // handle login action
248
      if (action.equals("login")) {
249
250
        handleLoginAction(response.getWriter(), params, request, response);
251
252
      // handle logout action
253
      } else if (action.equals("logout")) {
254
255
        handleLogoutAction(response.getWriter(), params, request, response);
256
257
      // aware of session expiration on every request
258
      } else {
259
260
        HttpSession sess = request.getSession(true);
261
        if (sess.isNew()) {
262
          // session expired or has not been stored b/w user requests
263
          username = "public";
264
          sess.setAttribute("username", username);
265
        } else {
266
          username = (String)sess.getAttribute("username");
267
          password = (String)sess.getAttribute("password");
268 802 bojilova
          groupnames = (String[])sess.getAttribute("groupnames");
269 798 jones
          try {
270
            sess_id = (String)sess.getId();
271
          } catch(IllegalStateException ise) {
272
            System.out.println("error in handleGetOrPost: this shouldn't " +
273
                               "happen: the session should be valid: " +
274
                               ise.getMessage());
275
          }
276
        }
277
      }
278
279 947 tao
       // Now that we know the session is valid, we can delegate the request
280 798 jones
      // to a particular action handler
281
      if(action.equals("query")) {
282 802 bojilova
        handleQuery(response.getWriter(),params,response,username,groupnames);
283 798 jones
      } else if(action.equals("squery")) {
284
        if(params.containsKey("query")) {
285 943 tao
         handleSQuery(response.getWriter(),params,response,username,groupnames);
286 798 jones
        } else {
287
          PrintWriter out = response.getWriter();
288
          out.println("Illegal action squery without \"query\" parameter");
289
        }
290 943 tao
      } else if (action.equals("export")) {
291 949 tao
292 943 tao
        handleExportAction(params, response, username, groupnames);
293 798 jones
      } else if (action.equals("read")) {
294 802 bojilova
        handleReadAction(params, response, username, groupnames);
295 798 jones
      } else if (action.equals("insert") || action.equals("update")) {
296 458 berkley
        PrintWriter out = response.getWriter();
297 798 jones
        if ( (username != null) &&  !username.equals("public") ) {
298 802 bojilova
          handleInsertOrUpdateAction(out,params,response,username,groupnames);
299 798 jones
        } else {
300
          out.println("Permission denied for " + action);
301
        }
302
      } else if (action.equals("delete")) {
303
        PrintWriter out = response.getWriter();
304
        if ( (username != null) &&  !username.equals("public") ) {
305 802 bojilova
          handleDeleteAction(out, params, response, username, groupnames);
306 798 jones
        } else {
307
          out.println("Permission denied for " + action);
308
        }
309
      } else if (action.equals("validate")) {
310
        PrintWriter out = response.getWriter();
311
        handleValidateAction(out, params, response);
312
      } else if (action.equals("getaccesscontrol")) {
313
        PrintWriter out = response.getWriter();
314 802 bojilova
        handleGetAccessControlAction(out,params,response,username,groupnames);
315 798 jones
      } else if (action.equals("getprincipals")) {
316
        PrintWriter out = response.getWriter();
317
        handleGetPrincipalsAction(out, username, password);
318
      } else if (action.equals("getdoctypes")) {
319
        PrintWriter out = response.getWriter();
320
        handleGetDoctypesAction(out, params, response);
321
      } else if (action.equals("getdtdschema")) {
322
        PrintWriter out = response.getWriter();
323
        handleGetDTDSchemaAction(out, params, response);
324
      } else if (action.equals("getdataguide")) {
325
        PrintWriter out = response.getWriter();
326
        handleGetDataGuideAction(out, params, response);
327
      } else if (action.equals("getlastdocid")) {
328
        PrintWriter out = response.getWriter();
329 847 jones
        handleGetMaxDocidAction(out, params, response);
330 798 jones
      } else if (action.equals("login") || action.equals("logout")) {
331
      } else if (action.equals("protocoltest")) {
332
        String testURL = "metacat://dev.nceas.ucsb.edu/NCEAS.897766.9";
333
        try {
334
          testURL = ((String[])params.get("url"))[0];
335
        } catch (Throwable t) {
336
        }
337
        String phandler = System.getProperty("java.protocol.handler.pkgs");
338
        response.setContentType("text/html");
339
        PrintWriter out = response.getWriter();
340
        out.println("<body bgcolor=\"white\">");
341
        out.println("<p>Handler property: <code>" + phandler + "</code></p>");
342
        out.println("<p>Starting test for:<br>");
343
        out.println("    " + testURL + "</p>");
344
        try {
345
          URL u = new URL(testURL);
346
          out.println("<pre>");
347
          out.println("Protocol: " + u.getProtocol());
348
          out.println("    Host: " + u.getHost());
349
          out.println("    Port: " + u.getPort());
350
          out.println("    Path: " + u.getPath());
351
          out.println("     Ref: " + u.getRef());
352
          String pquery = u.getQuery();
353
          out.println("   Query: " + pquery);
354
          out.println("  Params: ");
355
          if (pquery != null) {
356
            Hashtable qparams = util.parseQuery(u.getQuery());
357
            for (Enumeration en = qparams.keys(); en.hasMoreElements(); ) {
358
              String pname = (String)en.nextElement();
359
              String pvalue = (String)qparams.get(pname);
360
              out.println("    " + pname + ": " + pvalue);
361
            }
362 566 jones
          }
363 798 jones
          out.println("</pre>");
364
          out.println("</body>");
365
          out.close();
366
        } catch (MalformedURLException mue) {
367
          System.out.println("bad url from MetacatServlet.handleGetOrPost");
368
          out.println(mue.getMessage());
369
          mue.printStackTrace(out);
370
          out.close();
371 566 jones
        }
372 798 jones
      } else {
373
        PrintWriter out = response.getWriter();
374
        out.println("<?xml version=\"1.0\"?>");
375
        out.println("<error>");
376
        out.println("Error: action not registered.  Please report this error.");
377
        out.println("</error>");
378 566 jones
      }
379 798 jones
380
      util.closeConnections();
381
      // Close the stream to the client
382
      // out.close();
383 46 jones
    }
384
  }
385 355 berkley
386 731 bojilova
  // LOGIN & LOGOUT SECTION
387 50 jones
  /**
388 509 bojilova
   * Handle the login request. Create a new session object.
389 503 bojilova
   * Do user authentication through the session.
390 210 bojilova
   */
391
  private void handleLoginAction(PrintWriter out, Hashtable params,
392
               HttpServletRequest request, HttpServletResponse response) {
393 251 bojilova
394 503 bojilova
    AuthSession sess = null;
395 228 bojilova
    String un = ((String[])params.get("username"))[0];
396
    String pw = ((String[])params.get("password"))[0];
397 297 bojilova
    String action = ((String[])params.get("action"))[0];
398 509 bojilova
    String qformat = ((String[])params.get("qformat"))[0];
399 332 bojilova
400 297 bojilova
    try {
401 509 bojilova
      sess = new AuthSession();
402 297 bojilova
    } catch (Exception e) {
403 675 berkley
      System.out.println("error in MetacatServlet.handleLoginAction: " +
404
                          e.getMessage());
405 297 bojilova
      out.println(e.getMessage());
406 509 bojilova
      return;
407 297 bojilova
    }
408 509 bojilova
    boolean isValid = sess.authenticate(request, un, pw);
409
    // format and transform the output
410 832 jones
    if (qformat.equals("xml")) {
411
      response.setContentType("text/xml");
412
      out.println(sess.getMessage());
413
    } else {
414 509 bojilova
      Connection conn = null;
415 503 bojilova
      try {
416 509 bojilova
        conn = util.getConnection();
417
        DBTransform trans = new DBTransform(conn);
418
        response.setContentType("text/html");
419 510 bojilova
        trans.transformXMLDocument(sess.getMessage(), "-//NCEAS//login//EN",
420 832 jones
                                   "-//W3C//HTML//EN", qformat, out);
421 509 bojilova
        util.returnConnection(conn);
422
      } catch(Exception e) {
423
        util.returnConnection(conn);
424
      }
425
426
    // any output is returned
427 503 bojilova
    }
428 370 berkley
  }
429 509 bojilova
430
  /**
431
   * Handle the logout request. Close the connection.
432
   */
433
  private void handleLogoutAction(PrintWriter out, Hashtable params,
434
               HttpServletRequest request, HttpServletResponse response) {
435
436
    String qformat = ((String[])params.get("qformat"))[0];
437
438
    // close the connection
439
    HttpSession sess = request.getSession(false);
440
    if (sess != null) { sess.invalidate();  }
441
442
    // produce output
443
    StringBuffer output = new StringBuffer();
444
    output.append("<?xml version=\"1.0\"?>");
445 510 bojilova
    output.append("<logout>");
446
    output.append("User logged out");
447
    output.append("</logout>");
448 509 bojilova
449
    //format and transform the output
450 832 jones
    if (qformat.equals("xml")) {
451
      response.setContentType("text/xml");
452
      out.println(output.toString());
453
    } else {
454 509 bojilova
      Connection conn = null;
455
      try {
456
        conn = util.getConnection();
457
        DBTransform trans = new DBTransform(conn);
458
        response.setContentType("text/html");
459 510 bojilova
        trans.transformXMLDocument(output.toString(), "-//NCEAS//login//EN",
460 832 jones
                                   "-//W3C//HTML//EN", qformat, out);
461 509 bojilova
        util.returnConnection(conn);
462
      } catch(Exception e) {
463
        util.returnConnection(conn);
464
      }
465
    }
466
  }
467 731 bojilova
  // END OF LOGIN & LOGOUT SECTION
468 370 berkley
469 731 bojilova
  // SQUERY & QUERY SECTION
470 373 berkley
  /**
471 380 jones
   * Retreive the squery xml, execute it and display it
472
   *
473
   * @param out the output stream to the client
474
   * @param params the Hashtable of parameters that should be included
475
   * in the squery.
476
   * @param response the response object linked to the client
477
   * @param conn the database connection
478
   */
479
  protected void handleSQuery(PrintWriter out, Hashtable params,
480 802 bojilova
                 HttpServletResponse response, String user, String[] groups)
481 373 berkley
  {
482 380 jones
    String xmlquery = ((String[])params.get("query"))[0];
483
    String qformat = ((String[])params.get("qformat"))[0];
484 465 berkley
    String resultdoc = null;
485
486 802 bojilova
    Hashtable doclist = runQuery(xmlquery, user, groups);
487 444 berkley
488 465 berkley
    resultdoc = createResultDocument(doclist, transformQuery(xmlquery));
489
490 380 jones
    //format and transform the results
491 832 jones
    if(qformat.equals("xml")) {
492 380 jones
      response.setContentType("text/xml");
493
      out.println(resultdoc);
494
    } else {
495 832 jones
      transformResultset(resultdoc, response, out, qformat);
496 380 jones
    }
497 341 berkley
  }
498
499
   /**
500 380 jones
    * Create the xml query, execute it and display the results.
501
    *
502
    * @param out the output stream to the client
503
    * @param params the Hashtable of parameters that should be included
504 370 berkley
    * in the squery.
505 380 jones
    * @param response the response object linked to the client
506 370 berkley
    */
507 375 berkley
  protected void handleQuery(PrintWriter out, Hashtable params,
508 802 bojilova
                 HttpServletResponse response, String user, String[] groups)
509 341 berkley
  {
510 370 berkley
    //create the query and run it
511 373 berkley
    String xmlquery = DBQuery.createSQuery(params);
512 802 bojilova
    Hashtable doclist = runQuery(xmlquery, user, groups);
513 465 berkley
    String qformat = ((String[])params.get("qformat"))[0];
514
    String resultdoc = null;
515
516
    resultdoc = createResultDocument(doclist, transformQuery(params));
517 425 bojilova
518 370 berkley
    //format and transform the results
519 832 jones
    if(qformat.equals("xml")) {
520 370 berkley
      response.setContentType("text/xml");
521
      out.println(resultdoc);
522 443 berkley
    } else {
523 832 jones
      transformResultset(resultdoc, response, out, qformat);
524 370 berkley
    }
525 341 berkley
  }
526
527
  /**
528 384 berkley
   * Removes the <?xml version="x"?> tag from the beginning of xmlquery
529
   * so it can properly be placed in the <query> tag of the resultset.
530
   * This method is overwritable so that other applications can customize
531
   * the structure of what is in the <query> tag.
532
   *
533
   * @param xmlquery is the query to remove the <?xml version="x"?> tag from.
534
   */
535
  protected String transformQuery(Hashtable params)
536
  {
537
    //DBQuery.createSQuery is a re-calling of a previously called
538
    //function but it is necessary
539
    //so that overriding methods have access to the params hashtable
540
    String xmlquery = DBQuery.createSQuery(params);
541
    //the <?xml version="1.0"?> tag is the first 22 characters of the
542
    xmlquery = xmlquery.trim();
543
    int index = xmlquery.indexOf("?>");
544
    return xmlquery.substring(index + 2, xmlquery.length());
545
  }
546
547
  /**
548 443 berkley
   * removes the <?xml version="1.0"?> tag from the beginning.  This takes a
549
   * string as a param instead of a hashtable.
550
   *
551
   * @param xmlquery a string representing a query.
552
   */
553
  protected String transformQuery(String xmlquery)
554
  {
555
    xmlquery = xmlquery.trim();
556
    int index = xmlquery.indexOf("?>");
557
    return xmlquery.substring(index + 2, xmlquery.length());
558
  }
559
560
  /**
561 380 jones
   * Run the query and return a hashtable of results.
562
   *
563
   * @param xmlquery the query to run
564
   */
565 802 bojilova
  private Hashtable runQuery(String xmlquery, String user, String[] groups)
566 341 berkley
  {
567
    Hashtable doclist=null;
568
    Connection conn = null;
569
    try
570
    {
571 441 bojilova
      conn = util.getConnection();
572
      DBQuery queryobj = new DBQuery(conn, saxparser);
573 802 bojilova
      doclist = queryobj.findDocuments(new StringReader(xmlquery),user,groups);
574 441 bojilova
      util.returnConnection(conn);
575
      return doclist;
576 341 berkley
    }
577
    catch (Exception e)
578
    {
579 441 bojilova
      util.returnConnection(conn);
580 675 berkley
      util.debugMessage("Error in MetacatServlet.runQuery: " + e.getMessage());
581 341 berkley
      doclist = null;
582
      return doclist;
583
    }
584
  }
585
586 380 jones
  /**
587 370 berkley
   * Transorms an xml resultset document to html and sends it to the browser
588 380 jones
   *
589 370 berkley
   * @param resultdoc the string representation of the document that needs
590
   * to be transformed.
591
   * @param response the HttpServletResponse object bound to the client.
592
   * @param out the output stream to the client
593 832 jones
   * @param qformat the name of the style-set to use for transformations
594 375 berkley
   */
595
  protected void transformResultset(String resultdoc,
596 380 jones
                                    HttpServletResponse response,
597 832 jones
                                    PrintWriter out, String qformat)
598 370 berkley
  {
599
    Connection conn = null;
600 380 jones
    try {
601 370 berkley
      conn = util.getConnection();
602
      DBTransform trans = new DBTransform(conn);
603
      response.setContentType("text/html");
604
      trans.transformXMLDocument(resultdoc, "-//NCEAS//resultset//EN",
605 832 jones
                                 "-//W3C//HTML//EN", qformat, out);
606 382 berkley
      util.returnConnection(conn);
607
    }
608
    catch(Exception e)
609
    {
610 441 bojilova
      util.returnConnection(conn);
611 370 berkley
    }
612
  }
613
614 355 berkley
  /**
615
   * Transforms a hashtable of documents to an xml or html result.
616 380 jones
   *
617 355 berkley
   * @param doclist- the hashtable to transform
618 744 jones
   * @param xmlquery- the query that returned the doclist result
619 355 berkley
   */
620 375 berkley
  protected String createResultDocument(Hashtable doclist, String xmlquery)
621 341 berkley
  {
622
    // Create a buffer to hold the xml result
623
    StringBuffer resultset = new StringBuffer();
624
625 382 berkley
    // Print the resulting root nodes
626 341 berkley
    String docid = null;
627
    String document = null;
628
    resultset.append("<?xml version=\"1.0\"?>\n");
629
    resultset.append("<resultset>\n");
630 465 berkley
631 384 berkley
    resultset.append("  <query>" + xmlquery + "</query>");
632 478 berkley
633
    if(doclist != null)
634 341 berkley
    {
635 478 berkley
      Enumeration doclistkeys = doclist.keys();
636
      while (doclistkeys.hasMoreElements())
637
      {
638
        docid = (String)doclistkeys.nextElement();
639
        document = (String)doclist.get(docid);
640
        resultset.append("  <document>" + document + "</document>");
641
      }
642
    }
643
644 341 berkley
    resultset.append("</resultset>");
645 370 berkley
    return resultset.toString();
646 341 berkley
  }
647 731 bojilova
  // END OF SQUERY & QUERY SECTION
648 437 berkley
649 943 tao
 //Exoport section
650
 /**
651
   * Handle the "export" request of data package from Metacat in zip format
652
   * @param params the Hashtable of HTTP request parameters
653
   * @param response the HTTP response object linked to the client
654
   * @param user the username sent the request
655
   * @param groups the user's groupnames
656
   */
657
  private void handleExportAction(Hashtable params,
658
                    HttpServletResponse response, String user, String[] groups)
659
  {
660
    ServletOutputStream out = null;
661
    ZipOutputStream zOut = null;
662
    DocumentImpl docImpls=null;
663
    DBQuery queryObj=null;
664
    Connection conn = null;
665
    String[] docs = new String[10];
666
    String docId = "";
667
668
    try
669
    {
670
      // read the params
671
      if (params.containsKey("docid")) {
672
        docs = (String[])params.get("docid");
673
      }
674
675
      //get the connection to database
676
      conn = util.getConnection();
677
      queryObj = new DBQuery(conn, saxparser);//"saxparser" have to use though
678
                                              //it is not standard
679
      docId=docs[0];
680
      out = response.getOutputStream();
681
      response.setContentType("application/zip"); //MIME type
682
      zOut = new ZipOutputStream(out);
683
      zOut =queryObj.getZippedPackage(docId, out, user, groups);
684
      zOut.finish(); //terminate the zip file
685
      zOut.close();  //close the zip stream
686
    }
687
    catch (Exception e)
688
    {
689
      try
690
      {
691
        response.setContentType("text/xml"); //MIME type
692
        if (out != null)
693
        {
694
            PrintWriter pw = new PrintWriter(out);
695
            pw.println("<?xml version=\"1.0\"?>");
696
            pw.println("<error>");
697
            pw.println(e.getMessage());
698
            pw.println("</error>");
699
            pw.close();
700
        }
701
702
        if ( zOut != null )
703
        {
704
          zOut.close();
705
        }
706
      }
707
      catch (IOException ioe)
708
      {
709
        util.debugMessage("Problem with the servlet output " +
710
                           "in MetacatServlet.handleReadAction: " +
711
                           ioe.getMessage());
712
713
714
      }
715
716
      util.debugMessage("Error in MetacatServlet.handleReadAction: " +
717
                         e.getMessage());
718
719
    }//catch
720
721
  }//handleExportAction
722
723 731 bojilova
  // READ SECTION
724
  /**
725
   * Handle the "read" request of metadata/data files from Metacat
726
   * or any files from Internet;
727
   * transformed metadata XML document into HTML presentation if requested;
728
   * zip files when more than one were requested.
729
   *
730
   * @param params the Hashtable of HTTP request parameters
731
   * @param response the HTTP response object linked to the client
732
   * @param user the username sent the request
733 802 bojilova
   * @param groups the user's groupnames
734 437 berkley
   */
735 731 bojilova
  private void handleReadAction(Hashtable params, HttpServletResponse response,
736 802 bojilova
                                String user, String[] groups)
737 437 berkley
  {
738 731 bojilova
    ServletOutputStream out = null;
739
    ZipOutputStream zout = null;
740
741
    try {
742
      String[] docs = new String[0];
743
      String docid = "";
744
      String qformat = "";
745
      String abstrpath = null;
746
      boolean zip = false;
747
      // read the params
748
      if (params.containsKey("docid")) {
749
        docs = (String[])params.get("docid");
750 437 berkley
      }
751 731 bojilova
      if (params.containsKey("qformat")) {
752
        qformat = ((String[])params.get("qformat"))[0];
753 437 berkley
      }
754 731 bojilova
      if (params.containsKey("abstractpath")) {
755
        abstrpath = ((String[])params.get("abstractpath"))[0];
756 738 bojilova
        if ( !abstrpath.equals("") && (abstrpath != null) ) {
757
          viewAbstract(response, abstrpath, docs[0]);
758
          return;
759
        }
760 437 berkley
      }
761 731 bojilova
      if ( (docs.length > 1) || qformat.equals("zip") ) {
762
        zip = true;
763
        out = response.getOutputStream();
764
        response.setContentType("application/zip"); //MIME type
765
        zout = new ZipOutputStream(out);
766
      }
767
      // go through the list of docs to read
768
      for (int i=0; i < docs.length; i++ ) {
769
        try {
770
771
          URL murl = new URL(docs[i]);
772
          Hashtable murlQueryStr = util.parseQuery(murl.getQuery());
773
          // case docid="http://.../?docid=aaa"
774
          // or docid="metacat://.../?docid=bbb"
775
          if (murlQueryStr.containsKey("docid")) {
776
            // get only docid, eliminate the rest
777
            docid = (String)murlQueryStr.get("docid");
778
            if ( zip ) {
779 947 tao
              addDocToZip(docid, zout, user, groups);
780 731 bojilova
            } else {
781
              readFromMetacat(response, docid, qformat, abstrpath,
782 802 bojilova
                              user, groups, zip, zout);
783 731 bojilova
            }
784
785
          // case docid="http://.../filename"
786
          } else {
787
            docid = docs[i];
788
            if ( zip ) {
789 947 tao
              addDocToZip(docid, zout, user, groups);
790 731 bojilova
            } else {
791
              readFromURLConnection(response, docid);
792
            }
793
          }
794
795
        // case docid="ccc"
796
        } catch (MalformedURLException mue) {
797
          docid = docs[i];
798
          if ( zip ) {
799 947 tao
            addDocToZip(docid, zout, user, groups);
800 731 bojilova
          } else {
801
            readFromMetacat(response, docid, qformat, abstrpath,
802 802 bojilova
                            user, groups, zip, zout);
803 731 bojilova
          }
804
        }
805
806
      } /* end for */
807
808
      if ( zip ) {
809
        zout.finish(); //terminate the zip file
810
        zout.close();  //close the zip stream
811
      }
812
813 947 tao
814 731 bojilova
    } catch (Exception e) {
815
      try {
816 845 jones
        response.setContentType("text/xml"); //MIME type
817
        //PrintWriter pw = response.getWriter();
818
        if (out != null) {
819
            PrintWriter pw = new PrintWriter(out);
820
            pw.println("<?xml version=\"1.0\"?>");
821
            pw.println("<error>");
822
            pw.println(e.getMessage());
823
            pw.println("</error>");
824
            pw.close();
825
        }
826
        //if ( out != null ) { out.close(); }
827 731 bojilova
        if ( zout != null ) { zout.close(); }
828
      } catch (IOException ioe) {
829
        System.out.println("Problem with the servlet output " +
830
                           "in MetacatServlet.handleReadAction: " +
831
                           ioe.getMessage());
832
        ioe.printStackTrace(System.out);
833
834
      }
835
836
      System.out.println("Error in MetacatServlet.handleReadAction: " +
837 675 berkley
                         e.getMessage());
838 731 bojilova
      e.printStackTrace(System.out);
839 437 berkley
    }
840
841
  }
842 731 bojilova
843
  // read metadata or data from Metacat
844
  private void readFromMetacat(HttpServletResponse response, String docid,
845
                               String qformat, String abstrpath, String user,
846 943 tao
                             String[] groups, boolean zip, ZipOutputStream zout)
847 731 bojilova
               throws ClassNotFoundException, IOException, SQLException,
848
                      McdbException, Exception
849 453 berkley
  {
850
    Connection conn = null;
851 731 bojilova
    try {
852
      conn = util.getConnection();
853
      DocumentImpl doc = new DocumentImpl(conn, docid);
854 453 berkley
855 947 tao
      //check the permission for read
856
      if (!doc.hasReadPermission(conn, user, groups, docid))
857
      {
858
        Exception e = new Exception("User " + user + " does not have permission"
859
                       +" to read the document with the docid " + docid);
860
        util.returnConnection(conn);
861
        throw e;
862
      }
863
864 731 bojilova
      if ( doc.getRootNodeID() == 0 ) {
865
        // this is data file
866
        ServletOutputStream out = response.getOutputStream();
867
        String filepath = util.getOption("datafilepath");
868
        if(!filepath.endsWith("/")) {
869
          filepath += "/";
870
        }
871 846 berkley
        String filename = filepath + docid;      //MIME type
872 731 bojilova
        String contentType = getServletContext().getMimeType(filename);
873
        if (contentType == null) {
874
          if (filename.endsWith(".xml")) {
875
            contentType="text/xml";
876
          } else if (filename.endsWith(".css")) {
877
            contentType="text/css";
878
          } else if (filename.endsWith(".dtd")) {
879
            contentType="text/plain";
880
          } else if (filename.endsWith(".xsd")) {
881 733 bojilova
            contentType="text/xml";
882 731 bojilova
          } else if (filename.endsWith("/")) {
883 733 bojilova
            contentType="text/html";
884 731 bojilova
          } else {
885 733 bojilova
            File f = new File(filename);
886
            if ( f.isDirectory() ) {
887
              contentType="text/html";
888
            } else {
889
              contentType="application/octet-stream";
890
            }
891 453 berkley
          }
892
        }
893 731 bojilova
        response.setContentType(contentType);
894 733 bojilova
        // if we decide to use "application/octet-stream" for all data returns
895
        // response.setContentType("application/octet-stream");
896 731 bojilova
        FileInputStream fin = null;
897
        try {
898
          fin = new FileInputStream(filename);
899
          byte[] buf = new byte[4 * 1024]; // 4K buffer
900
          int b = fin.read(buf);
901
          while (b != -1) {
902
            out.write(buf, 0, b);
903
            b = fin.read(buf);
904 453 berkley
          }
905 731 bojilova
        } finally {
906
          if (fin != null) fin.close();
907 453 berkley
        }
908 731 bojilova
909
      } else {
910
        // this is metadata doc
911 832 jones
        if ( qformat.equals("xml") ) {
912
          // set content type first
913
          response.setContentType("text/xml");   //MIME type
914
          PrintWriter out = response.getWriter();
915
          doc.toXml(out);
916
        } else {
917 731 bojilova
          response.setContentType("text/html");  //MIME type
918
          PrintWriter out = response.getWriter();
919
920
          // Look up the document type
921
          String doctype = doc.getDoctype();
922
          // Transform the document to the new doctype
923
          DBTransform dbt = new DBTransform(conn);
924
          dbt.transformXMLDocument(doc.toString(),
925 832 jones
                                   doctype,"-//W3C//HTML//EN", qformat, out);
926 731 bojilova
        }
927
928 453 berkley
      }
929 731 bojilova
    } finally {
930
      util.returnConnection(conn);
931
    }
932
933
  }
934 453 berkley
935 731 bojilova
  // read data from URLConnection
936
  private void readFromURLConnection(HttpServletResponse response, String docid)
937
               throws IOException, MalformedURLException
938 566 jones
  {
939 731 bojilova
    ServletOutputStream out = response.getOutputStream();
940
    String contentType = getServletContext().getMimeType(docid); //MIME type
941
    if (contentType == null) {
942
      if (docid.endsWith(".xml")) {
943
        contentType="text/xml";
944
      } else if (docid.endsWith(".css")) {
945
        contentType="text/css";
946
      } else if (docid.endsWith(".dtd")) {
947
        contentType="text/plain";
948
      } else if (docid.endsWith(".xsd")) {
949 733 bojilova
        contentType="text/xml";
950 731 bojilova
      } else if (docid.endsWith("/")) {
951 733 bojilova
        contentType="text/html";
952 731 bojilova
      } else {
953 733 bojilova
        File f = new File(docid);
954
        if ( f.isDirectory() ) {
955
          contentType="text/html";
956
        } else {
957
          contentType="application/octet-stream";
958
        }
959 731 bojilova
      }
960
    }
961
    response.setContentType(contentType);
962 733 bojilova
    // if we decide to use "application/octet-stream" for all data returns
963
    // response.setContentType("application/octet-stream");
964 731 bojilova
965
    // this is http url
966
    URL url = new URL(docid);
967
    BufferedInputStream bis = null;
968 566 jones
    try {
969 731 bojilova
      bis = new BufferedInputStream(url.openStream());
970
      byte[] buf = new byte[4 * 1024]; // 4K buffer
971
      int b = bis.read(buf);
972
      while (b != -1) {
973
        out.write(buf, 0, b);
974
        b = bis.read(buf);
975 636 berkley
      }
976 731 bojilova
    } finally {
977
      if (bis != null) bis.close();
978 566 jones
    }
979 731 bojilova
980 566 jones
  }
981 636 berkley
982 731 bojilova
  // read file/doc and write to ZipOutputStream
983 947 tao
  private void addDocToZip(String docid, ZipOutputStream zout,
984
                              String user, String[] groups)
985 731 bojilova
               throws ClassNotFoundException, IOException, SQLException,
986
                      McdbException, Exception
987 636 berkley
  {
988 731 bojilova
    byte[] bytestring = null;
989
    ZipEntry zentry = null;
990
991
    try {
992
      URL url = new URL(docid);
993
994
      // this http url; read from URLConnection; add to zip
995
      zentry = new ZipEntry(docid);
996
      zout.putNextEntry(zentry);
997
      BufferedInputStream bis = null;
998
      try {
999
        bis = new BufferedInputStream(url.openStream());
1000
        byte[] buf = new byte[4 * 1024]; // 4K buffer
1001
        int b = bis.read(buf);
1002
        while(b != -1) {
1003
          zout.write(buf, 0, b);
1004
          b = bis.read(buf);
1005
        }
1006
      } finally {
1007
        if (bis != null) bis.close();
1008 636 berkley
      }
1009 731 bojilova
      zout.closeEntry();
1010
1011
    } catch (MalformedURLException mue) {
1012 661 berkley
1013 731 bojilova
      // this is metacat doc (data file or metadata doc)
1014
      Connection conn = null;
1015
      try {
1016
        conn = util.getConnection();
1017
        DocumentImpl doc = new DocumentImpl(conn, docid);
1018 947 tao
1019
        //check the permission for read
1020
        if (!doc.hasReadPermission(conn, user, groups, docid))
1021
        {
1022
          Exception e = new Exception("User " + user + " does not have "
1023
                    +"permission to read the document with the docid " + docid);
1024
          util.returnConnection(conn);
1025
          throw e;
1026
        }
1027
1028 731 bojilova
        if ( doc.getRootNodeID() == 0 ) {
1029
          // this is data file; add file to zip
1030
          String filepath = util.getOption("datafilepath");
1031
          if(!filepath.endsWith("/")) {
1032
            filepath += "/";
1033
          }
1034
          String filename = filepath + doc.getDocname();
1035
          zentry = new ZipEntry(filename);
1036
          zout.putNextEntry(zentry);
1037
          FileInputStream fin = null;
1038
          try {
1039
            fin = new FileInputStream(filename);
1040
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1041
            int b = fin.read(buf);
1042
            while (b != -1) {
1043
              zout.write(buf, 0, b);
1044
              b = fin.read(buf);
1045
            }
1046
          } finally {
1047
            if (fin != null) fin.close();
1048
          }
1049
          zout.closeEntry();
1050
1051
        } else {
1052
          // this is metadata doc; add doc to zip
1053
          bytestring = doc.toString().getBytes();
1054
          zentry = new ZipEntry(docid + ".xml");
1055
          zentry.setSize(bytestring.length);
1056
          zout.putNextEntry(zentry);
1057
          zout.write(bytestring, 0, bytestring.length);
1058
          zout.closeEntry();
1059 636 berkley
        }
1060 731 bojilova
      } finally {
1061
        util.returnConnection(conn);
1062 636 berkley
      }
1063
1064
    }
1065 731 bojilova
1066 636 berkley
  }
1067 731 bojilova
1068
  // view abstract within document
1069
  private void viewAbstract(HttpServletResponse response,
1070
                            String abstractpath, String docid)
1071
               throws ClassNotFoundException, IOException, SQLException,
1072
                      McdbException, Exception
1073
  {
1074 309 bojilova
    Connection conn = null;
1075 102 jones
    try {
1076 309 bojilova
      conn = util.getConnection();
1077 731 bojilova
1078
      Object[] abstracts = DBQuery.getNodeContent(abstractpath, docid, conn);
1079
1080
      response.setContentType("text/html");  //MIME type
1081
      PrintWriter out = response.getWriter();
1082
      out.println("<html><head><title>Abstract</title></head>");
1083
      out.println("<body bgcolor=\"white\"><h1>Abstract</h1>");
1084
      for (int i=0; i<abstracts.length; i++) {
1085
        out.println("<p>" + (String)abstracts[i] + "</p>");
1086
      }
1087
      out.println("</body></html>");
1088 85 jones
1089 309 bojilova
    } finally {
1090 320 bojilova
      util.returnConnection(conn);
1091 731 bojilova
    }
1092 49 jones
  }
1093 731 bojilova
  // END OF READ SECTION
1094
1095
  // INSERT/UPDATE SECTION
1096 55 jones
  /**
1097
   * Handle the database putdocument request and write an XML document
1098
   * to the database connection
1099
   */
1100 382 berkley
  private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params,
1101 802 bojilova
               HttpServletResponse response, String user, String[] groups) {
1102 59 jones
1103 309 bojilova
    Connection conn = null;
1104
1105 204 jones
    try {
1106
      // Get the document indicated
1107
      String[] doctext = (String[])params.get("doctext");
1108 557 bojilova
1109 680 bojilova
      String pub = null;
1110
      if (params.containsKey("public")) {
1111
        pub = ((String[])params.get("public"))[0];
1112 557 bojilova
      }
1113 680 bojilova
1114 598 bojilova
      StringReader dtd = null;
1115 680 bojilova
      if (params.containsKey("dtdtext")) {
1116 598 bojilova
        String[] dtdtext = (String[])params.get("dtdtext");
1117
        try {
1118 619 bojilova
          if ( !dtdtext[0].equals("") ) {
1119
            dtd = new StringReader(dtdtext[0]);
1120
          }
1121 598 bojilova
        } catch (NullPointerException npe) {}
1122
      }
1123 557 bojilova
1124 204 jones
      StringReader xml = null;
1125 695 bojilova
      boolean validate = false;
1126 204 jones
      try {
1127 695 bojilova
        // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1128
        // in order to decide whether to use validation parser
1129
        validate = validateXML(doctext[0]);
1130 204 jones
        xml = new StringReader(doctext[0]);
1131 59 jones
1132 204 jones
        String[] action = (String[])params.get("action");
1133
        String[] docid = (String[])params.get("docid");
1134
        String newdocid = null;
1135 203 jones
1136 204 jones
        String doAction = null;
1137
        if (action[0].equals("insert")) {
1138
          doAction = "INSERT";
1139
        } else if (action[0].equals("update")) {
1140
          doAction = "UPDATE";
1141
        }
1142 203 jones
1143 204 jones
        try {
1144 680 bojilova
          // get a connection from the pool
1145
          conn = util.getConnection();
1146 408 jones
1147 680 bojilova
          // write the document to the database
1148
          try {
1149
            String accNumber = docid[0];
1150
            if (accNumber.equals("")) {
1151
              accNumber = null;
1152 309 bojilova
            }
1153 680 bojilova
            newdocid = DocumentImpl.write(conn, xml, pub, dtd, doAction,
1154 802 bojilova
                                          accNumber, user, groups, validate);
1155 680 bojilova
          } catch (NullPointerException npe) {
1156
            newdocid = DocumentImpl.write(conn, xml, pub, dtd, doAction,
1157 802 bojilova
                                          null, user, groups, validate);
1158 680 bojilova
          }
1159 309 bojilova
        } finally {
1160 320 bojilova
          util.returnConnection(conn);
1161 309 bojilova
        }
1162
1163 204 jones
        // set content type and other response header fields first
1164
        response.setContentType("text/xml");
1165
        out.println("<?xml version=\"1.0\"?>");
1166
        out.println("<success>");
1167
        out.println("<docid>" + newdocid + "</docid>");
1168
        out.println("</success>");
1169
1170 203 jones
      } catch (NullPointerException npe) {
1171 204 jones
        response.setContentType("text/xml");
1172
        out.println("<?xml version=\"1.0\"?>");
1173
        out.println("<error>");
1174
        out.println(npe.getMessage());
1175
        out.println("</error>");
1176 55 jones
      }
1177 204 jones
    } catch (Exception e) {
1178
      response.setContentType("text/xml");
1179
      out.println("<?xml version=\"1.0\"?>");
1180
      out.println("<error>");
1181
      out.println(e.getMessage());
1182
      if (e instanceof SAXException) {
1183
        Exception e2 = ((SAXException)e).getException();
1184
        out.println("<error>");
1185 780 berkley
        try
1186
        {
1187
          out.println(e2.getMessage());
1188
        }
1189
        catch(NullPointerException npe)
1190
        {
1191
          out.println(e.getMessage());
1192
        }
1193 204 jones
        out.println("</error>");
1194
      }
1195
      //e.printStackTrace(out);
1196
      out.println("</error>");
1197 203 jones
    }
1198 55 jones
  }
1199 203 jones
1200
  /**
1201 695 bojilova
   * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... >
1202
   * in order to decide whether to use validation parser
1203
   */
1204
  private static boolean validateXML(String xmltext) throws IOException {
1205
1206
    StringReader xmlreader = new StringReader(xmltext);
1207
    StringBuffer cbuff = new StringBuffer();
1208
    java.util.Stack st = new java.util.Stack();
1209
    boolean validate = false;
1210
    int c;
1211
    int inx;
1212
1213
    // read from the stream until find the keywords
1214
    while ( (st.empty() || st.size()<4) && ((c = xmlreader.read()) != -1) ) {
1215
      cbuff.append((char)c);
1216
1217
      // "<!DOCTYPE" keyword is found; put it in the stack
1218
      if ( (inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1 ) {
1219
        cbuff = new StringBuffer();
1220
        st.push("<!DOCTYPE");
1221
      }
1222
      // "PUBLIC" keyword is found; put it in the stack
1223
      if ( (inx = cbuff.toString().indexOf("PUBLIC")) != -1 ) {
1224
        cbuff = new StringBuffer();
1225
        st.push("PUBLIC");
1226
      }
1227
      // "SYSTEM" keyword is found; put it in the stack
1228
      if ( (inx = cbuff.toString().indexOf("SYSTEM")) != -1 ) {
1229
        cbuff = new StringBuffer();
1230
        st.push("SYSTEM");
1231
      }
1232
      // ">" character is found; put it in the stack
1233
      // ">" is found twice: fisrt from <?xml ...?>
1234
      // and second from <!DOCTYPE ... >
1235
      if ( (inx = cbuff.toString().indexOf(">")) != -1 ) {
1236
        cbuff = new StringBuffer();
1237
        st.push(">");
1238
      }
1239
    }
1240
1241
    // close the stream
1242
    xmlreader.close();
1243
1244
    // check the stack whether it contains the keywords:
1245
    // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1246
    if ( st.size() == 4 ) {
1247
      if ( ((String)st.pop()).equals(">") &&
1248
           ( ((String)st.peek()).equals("PUBLIC") |
1249
             ((String)st.pop()).equals("SYSTEM") ) &&
1250
           ((String)st.pop()).equals("<!DOCTYPE") )  {
1251
        validate = true;
1252
      }
1253
    }
1254
1255
System.out.println("Validation is " + validate);
1256
    return validate;
1257
  }
1258 731 bojilova
  // END OF INSERT/UPDATE SECTION
1259 695 bojilova
1260 731 bojilova
  // DELETE SECTION
1261 695 bojilova
  /**
1262 203 jones
   * Handle the database delete request and delete an XML document
1263
   * from the database connection
1264
   */
1265
  private void handleDeleteAction(PrintWriter out, Hashtable params,
1266 802 bojilova
               HttpServletResponse response, String user, String[] groups) {
1267 203 jones
1268
    String[] docid = (String[])params.get("docid");
1269 309 bojilova
    Connection conn = null;
1270 203 jones
1271
    // delete the document from the database
1272
    try {
1273 309 bojilova
      // get a connection from the pool
1274
      conn = util.getConnection();
1275 203 jones
                                      // NOTE -- NEED TO TEST HERE
1276 408 jones
                                      // FOR EXISTENCE OF DOCID PARAM
1277 203 jones
                                      // BEFORE ACCESSING ARRAY
1278 375 berkley
      try {
1279 802 bojilova
        DocumentImpl.delete(conn, docid[0], user, groups);
1280 204 jones
        response.setContentType("text/xml");
1281
        out.println("<?xml version=\"1.0\"?>");
1282
        out.println("<success>");
1283 203 jones
        out.println("Document deleted.");
1284 204 jones
        out.println("</success>");
1285 203 jones
      } catch (AccessionNumberException ane) {
1286 204 jones
        response.setContentType("text/xml");
1287
        out.println("<?xml version=\"1.0\"?>");
1288
        out.println("<error>");
1289
        out.println("Error deleting document!!!");
1290 203 jones
        out.println(ane.getMessage());
1291 204 jones
        out.println("</error>");
1292 203 jones
      }
1293 204 jones
    } catch (Exception e) {
1294
      response.setContentType("text/xml");
1295
      out.println("<?xml version=\"1.0\"?>");
1296
      out.println("<error>");
1297
      out.println(e.getMessage());
1298
      out.println("</error>");
1299 309 bojilova
    } finally {
1300 320 bojilova
      util.returnConnection(conn);
1301 309 bojilova
    }
1302 203 jones
  }
1303 731 bojilova
  // END OF DELETE SECTION
1304 68 higgins
1305 731 bojilova
  // VALIDATE SECTION
1306 68 higgins
  /**
1307 380 jones
   * Handle the validation request and return the results to the requestor
1308 68 higgins
   */
1309 185 jones
  private void handleValidateAction(PrintWriter out, Hashtable params,
1310
               HttpServletResponse response) {
1311 68 higgins
1312 103 jones
    // Get the document indicated
1313
    String valtext = null;
1314 309 bojilova
1315 103 jones
    try {
1316
      valtext = ((String[])params.get("valtext"))[0];
1317
    } catch (Exception nullpe) {
1318 68 higgins
1319 309 bojilova
      Connection conn = null;
1320 162 bojilova
      String docid = null;
1321 103 jones
      try {
1322
        // Find the document id number
1323 185 jones
        docid = ((String[])params.get("docid"))[0];
1324 309 bojilova
1325
        // get a connection from the pool
1326
        conn = util.getConnection();
1327 393 jones
1328 309 bojilova
        // Get the document indicated from the db
1329 393 jones
        DocumentImpl xmldoc = new DocumentImpl(conn, docid);
1330
        valtext = xmldoc.toString();
1331 185 jones
1332 103 jones
      } catch (NullPointerException npe) {
1333 253 jones
        response.setContentType("text/xml");
1334
        out.println("<error>Error getting document ID: " + docid + "</error>");
1335 320 bojilova
        if ( conn != null ) { util.returnConnection(conn); }
1336 380 jones
        return;
1337 309 bojilova
      } catch (Exception e) {
1338
        response.setContentType("text/html");
1339
        out.println(e.getMessage());
1340
      } finally {
1341 320 bojilova
        util.returnConnection(conn);
1342 309 bojilova
      }
1343 103 jones
    }
1344 68 higgins
1345 309 bojilova
    Connection conn = null;
1346 103 jones
    try {
1347 309 bojilova
      // get a connection from the pool
1348
      conn = util.getConnection();
1349 253 jones
      DBValidate valobj = new DBValidate(saxparser,conn);
1350 185 jones
      boolean valid = valobj.validateString(valtext);
1351 68 higgins
1352
      // set content type and other response header fields first
1353 253 jones
      response.setContentType("text/xml");
1354
      out.println(valobj.returnErrors());
1355
1356 103 jones
    } catch (NullPointerException npe2) {
1357
      // set content type and other response header fields first
1358 253 jones
      response.setContentType("text/xml");
1359
      out.println("<error>Error validating document.</error>");
1360 309 bojilova
    } catch (Exception e) {
1361
      response.setContentType("text/html");
1362
      out.println(e.getMessage());
1363
    } finally {
1364 320 bojilova
      util.returnConnection(conn);
1365 309 bojilova
    }
1366 103 jones
  }
1367 731 bojilova
  // END OF VALIDATE SECTION
1368
1369
  // OTHER ACTION HANDLERS
1370 302 bojilova
1371
  /**
1372 688 bojilova
   * Handle "getaccesscontrol" action.
1373
   * Read Access Control List from db connection in XML format
1374
   */
1375
  private void handleGetAccessControlAction(PrintWriter out, Hashtable params,
1376
                                       HttpServletResponse response,
1377 802 bojilova
                                       String username, String[] groupnames) {
1378 688 bojilova
1379
    Connection conn = null;
1380
    String docid = ((String[])params.get("docid"))[0];
1381
1382
    try {
1383
1384
        // get connection from the pool
1385
        conn = util.getConnection();
1386
        AccessControlList aclobj = new AccessControlList(conn);
1387 802 bojilova
        String acltext = aclobj.getACL(docid, username, groupnames);
1388 688 bojilova
        out.println(acltext);
1389
1390
    } catch (Exception e) {
1391
      out.println("<?xml version=\"1.0\"?>");
1392
      out.println("<error>");
1393
      out.println(e.getMessage());
1394
      out.println("</error>");
1395
    } finally {
1396
      util.returnConnection(conn);
1397
    }
1398
1399
  }
1400
1401
  /**
1402 731 bojilova
   * Handle the "getprincipals" action.
1403
   * Read all principals from authentication scheme in XML format
1404
   */
1405
  private void handleGetPrincipalsAction(PrintWriter out, String user,
1406
                                         String password) {
1407
1408
    Connection conn = null;
1409
1410
    try {
1411
1412
        // get connection from the pool
1413
        AuthSession auth = new AuthSession();
1414
        String principals = auth.getPrincipals(user, password);
1415
        out.println(principals);
1416
1417
    } catch (Exception e) {
1418
      out.println("<?xml version=\"1.0\"?>");
1419
      out.println("<error>");
1420
      out.println(e.getMessage());
1421
      out.println("</error>");
1422
    } finally {
1423
      util.returnConnection(conn);
1424
    }
1425
1426
  }
1427
1428
  /**
1429 688 bojilova
   * Handle "getdoctypes" action.
1430 302 bojilova
   * Read all doctypes from db connection in XML format
1431
   */
1432
  private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
1433
                                       HttpServletResponse response) {
1434
1435 309 bojilova
    Connection conn = null;
1436
1437 302 bojilova
    try {
1438
1439 309 bojilova
        // get connection from the pool
1440
        conn = util.getConnection();
1441
        DBUtil dbutil = new DBUtil(conn);
1442 302 bojilova
        String doctypes = dbutil.readDoctypes();
1443
        out.println(doctypes);
1444
1445
    } catch (Exception e) {
1446
      out.println("<?xml version=\"1.0\"?>");
1447
      out.println("<error>");
1448
      out.println(e.getMessage());
1449
      out.println("</error>");
1450 309 bojilova
    } finally {
1451 320 bojilova
      util.returnConnection(conn);
1452 309 bojilova
    }
1453 302 bojilova
1454
  }
1455
1456
  /**
1457 699 bojilova
   * Handle the "getdtdschema" action.
1458
   * Read DTD or Schema file for a given doctype from Metacat catalog system
1459
   */
1460
  private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
1461
                                        HttpServletResponse response) {
1462
1463
    Connection conn = null;
1464
    String doctype = null;
1465
    String[] doctypeArr = (String[])params.get("doctype");
1466
1467
    // get only the first doctype specified in the list of doctypes
1468
    // it could be done for all doctypes in that list
1469
    if (doctypeArr != null) {
1470
        doctype = ((String[])params.get("doctype"))[0];
1471
    }
1472
1473
    try {
1474
1475
        // get connection from the pool
1476
        conn = util.getConnection();
1477
        DBUtil dbutil = new DBUtil(conn);
1478
        String dtdschema = dbutil.readDTDSchema(doctype);
1479
        out.println(dtdschema);
1480
1481
    } catch (Exception e) {
1482
      out.println("<?xml version=\"1.0\"?>");
1483
      out.println("<error>");
1484
      out.println(e.getMessage());
1485
      out.println("</error>");
1486
    } finally {
1487
      util.returnConnection(conn);
1488
    }
1489
1490
  }
1491
1492
  /**
1493 688 bojilova
   * Handle the "getdataguide" action.
1494 302 bojilova
   * Read Data Guide for a given doctype from db connection in XML format
1495
   */
1496
  private void handleGetDataGuideAction(PrintWriter out, Hashtable params,
1497
                                        HttpServletResponse response) {
1498
1499 309 bojilova
    Connection conn = null;
1500 316 bojilova
    String doctype = null;
1501
    String[] doctypeArr = (String[])params.get("doctype");
1502 309 bojilova
1503 316 bojilova
    // get only the first doctype specified in the list of doctypes
1504
    // it could be done for all doctypes in that list
1505
    if (doctypeArr != null) {
1506
        doctype = ((String[])params.get("doctype"))[0];
1507
    }
1508
1509 302 bojilova
    try {
1510
1511 309 bojilova
        // get connection from the pool
1512
        conn = util.getConnection();
1513
        DBUtil dbutil = new DBUtil(conn);
1514 316 bojilova
        String dataguide = dbutil.readDataGuide(doctype);
1515 302 bojilova
        out.println(dataguide);
1516
1517
    } catch (Exception e) {
1518
      out.println("<?xml version=\"1.0\"?>");
1519
      out.println("<error>");
1520
      out.println(e.getMessage());
1521
      out.println("</error>");
1522 309 bojilova
    } finally {
1523 320 bojilova
      util.returnConnection(conn);
1524 309 bojilova
    }
1525 302 bojilova
1526
  }
1527
1528 793 bojilova
  /**
1529
   * Handle the "getlastdocid" action.
1530
   * Get the latest docid with rev number from db connection in XML format
1531
   */
1532 847 jones
  private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
1533 793 bojilova
                                        HttpServletResponse response) {
1534
1535
    Connection conn = null;
1536 847 jones
    String scope = ((String[])params.get("scope"))[0];
1537
    if (scope == null) {
1538
        scope = ((String[])params.get("username"))[0];
1539
    }
1540 793 bojilova
1541
    try {
1542
1543
        // get connection from the pool
1544
        conn = util.getConnection();
1545
        DBUtil dbutil = new DBUtil(conn);
1546 847 jones
        String lastDocid = dbutil.getMaxDocid(scope);
1547 793 bojilova
        out.println("<?xml version=\"1.0\"?>");
1548
        out.println("<lastDocid>");
1549 847 jones
        out.println("  <scope>" + scope + "</scope>");
1550 793 bojilova
        out.println("  <docid>" + lastDocid + "</docid>");
1551
        out.println("</lastDocid>");
1552
1553
    } catch (Exception e) {
1554
      out.println("<?xml version=\"1.0\"?>");
1555
      out.println("<error>");
1556
      out.println(e.getMessage());
1557
      out.println("</error>");
1558
    } finally {
1559
      util.returnConnection(conn);
1560
    }
1561
1562
  }
1563
1564 798 jones
  /**
1565
   * Handle documents passed to metacat that are encoded using the
1566
   * "multipart/form-data" mime type.  This is typically used for uploading
1567
   * data files which may be binary and large.
1568
   */
1569
  private void handleMultipartForm(HttpServletRequest request,
1570
                                   HttpServletResponse response)
1571
  {
1572
    PrintWriter out = null;
1573
    String action = null;
1574
1575
    // Parse the multipart form, and save the parameters in a Hashtable and
1576
    // save the FileParts in a hashtable
1577
1578
    Hashtable params = new Hashtable();
1579
    Hashtable fileList = new Hashtable();
1580
1581
    try {
1582
      // MBJ: need to put filesize limit in Metacat config (metacat.properties)
1583 943 tao
      MultipartParser mp = new MultipartParser(request, 200*1024*1024); //200MB
1584 798 jones
      Part part;
1585
      while ((part = mp.readNextPart()) != null) {
1586
        String name = part.getName();
1587
1588
        if (part.isParam()) {
1589
          // it's a parameter part
1590
          ParamPart paramPart = (ParamPart) part;
1591
          String value = paramPart.getStringValue();
1592
          params.put(name, value);
1593
          if (name.equals("action")) {
1594
            action = value;
1595
          }
1596
        } else if (part.isFile()) {
1597
          // it's a file part
1598
          FilePart filePart = (FilePart) part;
1599
          fileList.put(name, filePart);
1600
1601
          // Stop once the first file part is found, otherwise going onto the
1602
          // next part prevents access to the file contents.  So...for upload
1603
          // to work, the datafile must be the last part
1604
          break;
1605
        }
1606
      }
1607
    } catch (IOException ioe) {
1608
      try {
1609
        out = response.getWriter();
1610
      } catch (IOException ioe2) {
1611
        System.err.println("Fatal Error: couldn't get response output stream.");
1612
      }
1613
      out.println("<?xml version=\"1.0\"?>");
1614
      out.println("<error>");
1615
      out.println("Error: problem reading multipart data.");
1616
      out.println("</error>");
1617
    }
1618
1619
    // Get the session information
1620
    String username = null;
1621
    String password = null;
1622 802 bojilova
    String[] groupnames = null;
1623 798 jones
    String sess_id = null;
1624
1625
    // be aware of session expiration on every request
1626
    HttpSession sess = request.getSession(true);
1627
    if (sess.isNew()) {
1628
      // session expired or has not been stored b/w user requests
1629
      username = "public";
1630
      sess.setAttribute("username", username);
1631
    } else {
1632
      username = (String)sess.getAttribute("username");
1633
      password = (String)sess.getAttribute("password");
1634 802 bojilova
      groupnames = (String[])sess.getAttribute("groupnames");
1635 798 jones
      try {
1636
        sess_id = (String)sess.getId();
1637
      } catch(IllegalStateException ise) {
1638
        System.out.println("error in  handleMultipartForm: this shouldn't " +
1639
                           "happen: the session should be valid: " +
1640
                           ise.getMessage());
1641
      }
1642
    }
1643
1644
    if ( action.equals("upload")) {
1645
      if (username != null &&  !username.equals("public")) {
1646
        handleUploadAction(request, response, params, fileList,
1647 802 bojilova
                           username, groupnames);
1648 798 jones
      } else {
1649
        try {
1650
          out = response.getWriter();
1651
        } catch (IOException ioe2) {
1652 943 tao
          util.debugMessage("Fatal Error: couldn't get response "+
1653
                                                              "output stream.");
1654 798 jones
        }
1655
        out.println("<?xml version=\"1.0\"?>");
1656
        out.println("<error>");
1657
        out.println("Permission denied for " + action);
1658
        out.println("</error>");
1659
      }
1660
    } else {
1661
      try {
1662
        out = response.getWriter();
1663
      } catch (IOException ioe2) {
1664
        System.err.println("Fatal Error: couldn't get response output stream.");
1665
      }
1666
      out.println("<?xml version=\"1.0\"?>");
1667
      out.println("<error>");
1668
      out.println("Error: action not registered.  Please report this error.");
1669
      out.println("</error>");
1670
    }
1671
  }
1672
1673
  /**
1674
   * Handle the upload action by saving the attached file to disk and
1675
   * registering it in the Metacat db
1676
   */
1677
  private void handleUploadAction(HttpServletRequest request,
1678
                                  HttpServletResponse response,
1679
                                  Hashtable params, Hashtable fileList,
1680 802 bojilova
                                  String username, String[] groupnames)
1681 798 jones
  {
1682
    PrintWriter out = null;
1683
    Connection conn = null;
1684
    String action = null;
1685
    String docid = null;
1686
1687
    response.setContentType("text/xml");
1688
    try {
1689
      out = response.getWriter();
1690
    } catch (IOException ioe2) {
1691
      System.err.println("Fatal Error: couldn't get response output stream.");
1692
    }
1693
1694
    if (params.containsKey("docid")) {
1695
      docid = (String)params.get("docid");
1696
    }
1697
1698
    // Make sure we have a docid and datafile
1699
    if (docid != null && fileList.containsKey("datafile")) {
1700
1701
      // Get a reference to the file part of the form
1702
      FilePart filePart = (FilePart)fileList.get("datafile");
1703
      String fileName = filePart.getFileName();
1704
      MetaCatUtil.debugMessage("Uploading filename: " + fileName);
1705
1706
      // Check if the right file existed in the uploaded data
1707
      if (fileName != null) {
1708
1709 1028 tao
        try
1710
        {
1711
           //If document get lock data file grant
1712
           if (DocumentImpl.getDataFileLockGrant(docid))
1713
           {
1714
               // register the file in the database (which generates an exception
1715
              //if the docid is not acceptable or other untoward things happen
1716
              DocumentImpl.registerDocument(fileName, "BIN", docid, username);
1717 798 jones
1718 1028 tao
              // Save the data file to disk using "docid" as the name
1719
              dataDirectory.mkdirs();
1720
              File newFile = new File(dataDirectory, docid);
1721
              long size = filePart.writeTo(newFile);
1722
              if ((util.getOption("replicationdata")).equals("on"))
1723
              {
1724
                // force replcation data file if metacat was configured
1725
                ForceReplicationHandler frh = new
1726
                               ForceReplicationHandler(docid, "insert", false);
1727
              }
1728
              // set content type and other response header fields first
1729
              out.println("<?xml version=\"1.0\"?>");
1730
              out.println("<success>");
1731
              out.println("<docid>" + docid + "</docid>");
1732
              out.println("<size>" + size + "</size>");
1733
              out.println("</success>");
1734
            }//if
1735 798 jones
1736 1028 tao
        } //try
1737
        catch (Exception e) {
1738 798 jones
          out.println("<?xml version=\"1.0\"?>");
1739
          out.println("<error>");
1740
          out.println(e.getMessage());
1741
          out.println("</error>");
1742
        }
1743
      } else {
1744
        // the field did not contain a file
1745
        out.println("<?xml version=\"1.0\"?>");
1746
        out.println("<error>");
1747
        out.println("The uploaded data did not contain a valid file.");
1748
        out.println("</error>");
1749
      }
1750
    } else {
1751
      // Error bcse docid missing or file missing
1752
      out.println("<?xml version=\"1.0\"?>");
1753
      out.println("<error>");
1754
      out.println("The uploaded data did not contain a valid docid " +
1755
                  "or valid file.");
1756
      out.println("</error>");
1757
    }
1758
  }
1759 46 jones
}