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