Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements a metadata catalog as a java Servlet
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Matt Jones, Dan Higgins, Jivka Bojilova, Chad Berkley
7
 *    Release: @release@
8
 *
9
 *   '$Author: sgarg $'
10
 *     '$Date: 2004-09-16 11:15:49 -0700 (Thu, 16 Sep 2004) $'
11
 * '$Revision: 2292 $'
12
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
 */
27

    
28
package edu.ucsb.nceas.metacat;
29

    
30
import java.io.BufferedInputStream;
31
import java.io.File;
32
import java.io.FileInputStream;
33
import java.io.IOException;
34
import java.io.PrintWriter;
35
import java.io.StringReader;
36
import java.net.MalformedURLException;
37
import java.net.URL;
38
import java.sql.PreparedStatement;
39
import java.sql.ResultSet;
40
import java.sql.SQLException;
41
import java.sql.Timestamp;
42
import java.text.ParseException;
43
import java.text.SimpleDateFormat;
44
import java.util.Enumeration;
45
import java.util.Hashtable;
46
import java.util.PropertyResourceBundle;
47
import java.util.Vector;
48
import java.util.zip.ZipEntry;
49
import java.util.zip.ZipOutputStream;
50

    
51
import javax.servlet.ServletConfig;
52
import javax.servlet.ServletContext;
53
import javax.servlet.ServletException;
54
import javax.servlet.ServletOutputStream;
55
import javax.servlet.http.HttpServlet;
56
import javax.servlet.http.HttpServletRequest;
57
import javax.servlet.http.HttpServletResponse;
58
import javax.servlet.http.HttpSession;
59

    
60
import edu.ucsb.nceas.utilities.Options;
61

    
62
import org.ecoinformatics.eml.EMLParser;
63

    
64
import com.oreilly.servlet.multipart.FilePart;
65
import com.oreilly.servlet.multipart.MultipartParser;
66
import com.oreilly.servlet.multipart.ParamPart;
67
import com.oreilly.servlet.multipart.Part;
68

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

    
116
    private ServletConfig config = null;
117

    
118
    private ServletContext context = null;
119

    
120
    private String resultStyleURL = null;
121

    
122
    private String xmlcatalogfile = null;
123

    
124
    private String saxparser = null;
125

    
126
    private String datafilepath = null;
127

    
128
    private File dataDirectory = null;
129

    
130
    private String servletpath = null;
131

    
132
    private String htmlpath = null;
133

    
134
    private PropertyResourceBundle options = null;
135

    
136
    private MetaCatUtil util = null;
137

    
138
    private DBConnectionPool connPool = null;
139

    
140
    private Hashtable sessionHash = new Hashtable();
141

    
142
    private static final String PROLOG = "<?xml version=\"1.0\"?>";
143

    
144
    private static final String SUCCESS = "<success>";
145

    
146
    private static final String SUCCESSCLOSE = "</success>";
147

    
148
    private static final String ERROR = "<error>";
149

    
150
    private static final String ERRORCLOSE = "</error>";
151

    
152
    public static final String SCHEMALOCATIONKEYWORD = ":schemaLocation";
153

    
154
    public static final String NONAMESPACELOCATION = ":noNamespaceSchemaLocation";
155

    
156
    public static final String EML2KEYWORD = ":eml";
157

    
158
    public static final String XMLFORMAT = "xml";
159

    
160
    private static final String CONFIG_DIR = "WEB-INF";
161

    
162
    private static final String CONFIG_NAME = "metacat.properties";
163

    
164
    /**
165
     * Initialize the servlet by creating appropriate database connections
166
     */
167
    public void init(ServletConfig config) throws ServletException
168
    {
169
        try {
170
            super.init(config);
171
            this.config = config;
172
            this.context = config.getServletContext();
173

    
174
            // Initialize the properties file for our options
175
            String dirPath = context.getRealPath(CONFIG_DIR);
176
            File propertyFile = new File(dirPath, CONFIG_NAME);
177
            Options options = null;
178
            try {
179
                options = Options.initialize(propertyFile);
180
                MetaCatUtil.debugMessage("Options configured: "
181
                        + options.getOption("configured"), 20);
182
            } catch (IOException ioe) {
183
                MetaCatUtil.debugMessage("Error in loading options: "
184
                        + ioe.getMessage(), 20);
185
            }
186

    
187
            util = new MetaCatUtil();
188

    
189
            //initial DBConnection pool
190
            connPool = DBConnectionPool.getInstance();
191

    
192
            // Get the configuration file information
193
            resultStyleURL = MetaCatUtil.getOption("resultStyleURL");
194
            xmlcatalogfile = MetaCatUtil.getOption("xmlcatalogfile");
195
            saxparser = MetaCatUtil.getOption("saxparser");
196
            datafilepath = MetaCatUtil.getOption("datafilepath");
197
            dataDirectory = new File(datafilepath);
198
            servletpath = MetaCatUtil.getOption("servletpath");
199
            htmlpath = MetaCatUtil.getOption("htmlpath");
200

    
201
            System.out.println("Metacat (" + Version.getVersion()
202
                    + ") initialized.");
203
        } catch (ServletException ex) {
204
            throw ex;
205
        } catch (SQLException e) {
206
            MetaCatUtil.debugMessage("Error in MetacatServlet.init: "
207
                    + e.getMessage(), 20);
208
        }
209
    }
210

    
211
    /**
212
     * Close all db connections from the pool
213
     */
214
    public void destroy()
215
    {
216
        // Close all db connection
217
        System.out.println("Destroying MetacatServlet");
218
        DBConnectionPool.release();
219
    }
220

    
221
    /** Handle "GET" method requests from HTTP clients */
222
    public void doGet(HttpServletRequest request, HttpServletResponse response)
223
            throws ServletException, IOException
224
    {
225

    
226
        // Process the data and send back the response
227
        handleGetOrPost(request, response);
228
    }
229

    
230
    /** Handle "POST" method requests from HTTP clients */
231
    public void doPost(HttpServletRequest request, HttpServletResponse response)
232
            throws ServletException, IOException
233
    {
234

    
235
        // Process the data and send back the response
236
        handleGetOrPost(request, response);
237
    }
238

    
239
    /**
240
     * Control servlet response depending on the action parameter specified
241
     */
242
    private void handleGetOrPost(HttpServletRequest request,
243
            HttpServletResponse response) throws ServletException, IOException
244
    {
245

    
246
        if (util == null) {
247
            util = new MetaCatUtil();
248
        }
249
        /*
250
         * MetaCatUtil.debugMessage("Connection pool size: "
251
         * +connPool.getSizeOfDBConnectionPool(),10);
252
         * MetaCatUtil.debugMessage("Free DBConnection number: "
253
         */
254
        //If all DBConnection in the pool are free and DBConnection pool
255
        //size is greater than initial value, shrink the connection pool
256
        //size to initial value
257
        DBConnectionPool.shrinkDBConnectionPoolSize();
258

    
259
        //Debug message to print out the method which have a busy DBConnection
260
        connPool.printMethodNameHavingBusyDBConnection();
261

    
262
        String ctype = request.getContentType();
263
        if (ctype != null && ctype.startsWith("multipart/form-data")) {
264
            handleMultipartForm(request, response);
265
        } else {
266

    
267
            String name = null;
268
            String[] value = null;
269
            String[] docid = new String[3];
270
            Hashtable params = new Hashtable();
271
            Enumeration paramlist = request.getParameterNames();
272

    
273
            while (paramlist.hasMoreElements()) {
274

    
275
                name = (String) paramlist.nextElement();
276
                value = request.getParameterValues(name);
277

    
278
                // Decode the docid and mouse click information
279
                if (name.endsWith(".y")) {
280
                    docid[0] = name.substring(0, name.length() - 2);
281
                    params.put("docid", docid);
282
                    name = "ypos";
283
                }
284
                if (name.endsWith(".x")) {
285
                    name = "xpos";
286
                }
287

    
288
                params.put(name, value);
289
            }
290

    
291
            //handle param is emptpy
292
            if (params.isEmpty() || params == null) { return; }
293

    
294
            //if the user clicked on the input images, decode which image
295
            //was clicked then set the action.
296
            if(params.get("action") == null){
297
                PrintWriter out = response.getWriter();
298
                response.setContentType("text/xml");
299
                out.println("<?xml version=\"1.0\"?>");
300
                out.println("<error>");
301
                out.println("Action not specified");
302
                out.println("</error>");
303
                out.close();
304
                return;
305
            }
306

    
307
            String action = ((String[]) params.get("action"))[0];
308
            MetaCatUtil.debugMessage("Line 230: Action is: " + action, 1);
309

    
310
            // This block handles session management for the servlet
311
            // by looking up the current session information for all actions
312
            // other than "login" and "logout"
313
            String username = null;
314
            String password = null;
315
            String[] groupnames = null;
316
            String sess_id = null;
317

    
318
            // handle login action
319
            if (action.equals("login")) {
320
                PrintWriter out = response.getWriter();
321
                handleLoginAction(out, params, request, response);
322
                out.close();
323

    
324
                // handle logout action
325
            } else if (action.equals("logout")) {
326
                PrintWriter out = response.getWriter();
327
                handleLogoutAction(out, params, request, response);
328
                out.close();
329

    
330
                // handle shrink DBConnection request
331
            } else if (action.equals("shrink")) {
332
                PrintWriter out = response.getWriter();
333
                boolean success = false;
334
                //If all DBConnection in the pool are free and DBConnection
335
                // pool
336
                //size is greater than initial value, shrink the connection
337
                // pool
338
                //size to initial value
339
                success = DBConnectionPool.shrinkConnectionPoolSize();
340
                if (success) {
341
                    //if successfully shrink the pool size to initial value
342
                    out.println("DBConnection Pool shrunk successfully.");
343
                }//if
344
                else {
345
                    out.println("DBConnection pool not shrunk successfully.");
346
                }
347
                //close out put
348
                out.close();
349

    
350
                // aware of session expiration on every request
351
            } else {
352
                HttpSession sess = request.getSession(true);
353
                if (sess.isNew() && !params.containsKey("sessionid")) {
354
                    // session expired or has not been stored b/w user requests
355
                    MetaCatUtil.debugMessage(
356
                            "in session is new or no sessionid", 40);
357
                    username = "public";
358
                    sess.setAttribute("username", username);
359
                } else {
360
                    MetaCatUtil.debugMessage("in session is not new or "
361
                            + " has sessionid parameter", 40);
362
                    try {
363
                        if (params.containsKey("sessionid")) {
364
                            sess_id = ((String[]) params.get("sessionid"))[0];
365
                            MetaCatUtil.debugMessage("in has sessionid "
366
                                    + sess_id, 40);
367
                            if (sessionHash.containsKey(sess_id)) {
368
                                MetaCatUtil.debugMessage("find the id "
369
                                        + sess_id + " in hash table", 40);
370
                                sess = (HttpSession) sessionHash.get(sess_id);
371
                            }
372
                        } else {
373
                            // we already store the session in login, so we
374
                            // don't need here
375
                            /*
376
                             * MetaCatUtil.debugMessage("in no sessionid
377
                             * parameter ", 40); sess_id =
378
                             * (String)sess.getId();
379
                             * MetaCatUtil.debugMessage("storing the session id "
380
                             * + sess_id + " which has username " +
381
                             * sess.getAttribute("username") + " into session
382
                             * hash in handleGetOrPost method", 35);
383
                             */
384
                        }
385
                    } catch (IllegalStateException ise) {
386
                        System.out.println(
387
                                "error in handleGetOrPost: this shouldn't "
388
                                + "happen: the session should be valid: "
389
                                + ise.getMessage());
390
                    }
391

    
392
                    username = (String) sess.getAttribute("username");
393
                    MetaCatUtil.debugMessage("The user name from session is: "
394
                            + username, 20);
395
                    password = (String) sess.getAttribute("password");
396
                    groupnames = (String[]) sess.getAttribute("groupnames");
397
                }
398

    
399
                //make user user username should be public
400
                if (username == null || (username.trim().equals(""))) {
401
                    username = "public";
402
                }
403
                MetaCatUtil.debugMessage("The user is : " + username, 5);
404
            }
405
            // Now that we know the session is valid, we can delegate the
406
            // request
407
            // to a particular action handler
408
            if (action.equals("query")) {
409
                PrintWriter out = response.getWriter();
410
                handleQuery(out, params, response, username, groupnames,
411
                        sess_id);
412
                out.close();
413
            } else if (action.equals("squery")) {
414
                PrintWriter out = response.getWriter();
415
                if (params.containsKey("query")) {
416
                    handleSQuery(out, params, response, username, groupnames,
417
                            sess_id);
418
                    out.close();
419
                } else {
420
                    out.println(
421
                            "Illegal action squery without \"query\" parameter");
422
                    out.close();
423
                }
424
            } else if (action.equals("export")) {
425

    
426
                handleExportAction(params, response, username,
427
                        groupnames, password);
428
            } else if (action.equals("read")) {
429
                handleReadAction(params, request, response, username, password,
430
                        groupnames);
431
            } else if (action.equals("readinlinedata")) {
432
                handleReadInlineDataAction(params, request, response, username,
433
                        password, groupnames);
434
            } else if (action.equals("insert") || action.equals("update")) {
435
                PrintWriter out = response.getWriter();
436
                if ((username != null) && !username.equals("public")) {
437
                    handleInsertOrUpdateAction(request, response,
438
                            out, params, username, groupnames);
439
                } else {
440
                    response.setContentType("text/xml");
441
                    out.println("<?xml version=\"1.0\"?>");
442
                    out.println("<error>");
443
                    out.println("Permission denied for user " + username + " "
444
                            + action);
445
                    out.println("</error>");
446
                }
447
                out.close();
448
            } else if (action.equals("delete")) {
449
                PrintWriter out = response.getWriter();
450
                if ((username != null) && !username.equals("public")) {
451
                    handleDeleteAction(out, params, request, response, username,
452
                            groupnames);
453
                } else {
454
                    response.setContentType("text/xml");
455
                    out.println("<?xml version=\"1.0\"?>");
456
                    out.println("<error>");
457
                    out.println("Permission denied for " + action);
458
                    out.println("</error>");
459
                }
460
                out.close();
461
            } else if (action.equals("validate")) {
462
                PrintWriter out = response.getWriter();
463
                handleValidateAction(out, params);
464
                out.close();
465
            } else if (action.equals("setaccess")) {
466
                PrintWriter out = response.getWriter();
467
                handleSetAccessAction(out, params, username);
468
                out.close();
469
            } else if (action.equals("getaccesscontrol")) {
470
                PrintWriter out = response.getWriter();
471
                handleGetAccessControlAction(out, params, response, username,
472
                        groupnames);
473
                out.close();
474
            } else if (action.equals("getprincipals")) {
475
                PrintWriter out = response.getWriter();
476
                handleGetPrincipalsAction(out, username, password);
477
                out.close();
478
            } else if (action.equals("getdoctypes")) {
479
                PrintWriter out = response.getWriter();
480
                handleGetDoctypesAction(out, params, response);
481
                out.close();
482
            } else if (action.equals("getdtdschema")) {
483
                PrintWriter out = response.getWriter();
484
                handleGetDTDSchemaAction(out, params, response);
485
                out.close();
486
            } else if (action.equals("getlastdocid")) {
487
                PrintWriter out = response.getWriter();
488
                handleGetMaxDocidAction(out, params, response);
489
                out.close();
490
            } else if (action.equals("getrevisionanddoctype")) {
491
                PrintWriter out = response.getWriter();
492
                handleGetRevisionAndDocTypeAction(out, params);
493
                out.close();
494
            } else if (action.equals("getversion")) {
495
                response.setContentType("text/xml");
496
                PrintWriter out = response.getWriter();
497
                out.println(Version.getVersionAsXml());
498
                out.close();
499
            } else if (action.equals("getlog")) {
500
                handleGetLogAction(params, request, response);
501
            } else if (action.equals("login") || action.equals("logout")) {
502
            } else if (action.equals("protocoltest")) {
503
                String testURL = "metacat://dev.nceas.ucsb.edu/NCEAS.897766.9";
504
                try {
505
                    testURL = ((String[]) params.get("url"))[0];
506
                } catch (Throwable t) {
507
                }
508
                String phandler = System
509
                        .getProperty("java.protocol.handler.pkgs");
510
                response.setContentType("text/html");
511
                PrintWriter out = response.getWriter();
512
                out.println("<body bgcolor=\"white\">");
513
                out.println("<p>Handler property: <code>" + phandler
514
                        + "</code></p>");
515
                out.println("<p>Starting test for:<br>");
516
                out.println("    " + testURL + "</p>");
517
                try {
518
                    URL u = new URL(testURL);
519
                    out.println("<pre>");
520
                    out.println("Protocol: " + u.getProtocol());
521
                    out.println("    Host: " + u.getHost());
522
                    out.println("    Port: " + u.getPort());
523
                    out.println("    Path: " + u.getPath());
524
                    out.println("     Ref: " + u.getRef());
525
                    String pquery = u.getQuery();
526
                    out.println("   Query: " + pquery);
527
                    out.println("  Params: ");
528
                    if (pquery != null) {
529
                        Hashtable qparams = MetaCatUtil.parseQuery(u.getQuery());
530
                        for (Enumeration en = qparams.keys(); en
531
                                .hasMoreElements();) {
532
                            String pname = (String) en.nextElement();
533
                            String pvalue = (String) qparams.get(pname);
534
                            out.println("    " + pname + ": " + pvalue);
535
                        }
536
                    }
537
                    out.println("</pre>");
538
                    out.println("</body>");
539
                    out.close();
540
                } catch (MalformedURLException mue) {
541
                    System.out.println(
542
                            "bad url from MetacatServlet.handleGetOrPost");
543
                    out.println(mue.getMessage());
544
                    mue.printStackTrace(out);
545
                    out.close();
546
                }
547
            } else {
548
                PrintWriter out = response.getWriter();
549
                out.println("<?xml version=\"1.0\"?>");
550
                out.println("<error>");
551
                out.println(
552
                     "Error: action not registered.  Please report this error.");
553
                out.println("</error>");
554
                out.close();
555
            }
556

    
557
            //util.closeConnections();
558
            // Close the stream to the client
559
            //out.close();
560
        }
561
    }
562

    
563
    // LOGIN & LOGOUT SECTION
564
    /**
565
     * Handle the login request. Create a new session object. Do user
566
     * authentication through the session.
567
     */
568
    private void handleLoginAction(PrintWriter out, Hashtable params,
569
            HttpServletRequest request, HttpServletResponse response)
570
    {
571

    
572
        AuthSession sess = null;
573

    
574
        if(params.get("username") == null){
575
            response.setContentType("text/xml");
576
            out.println("<?xml version=\"1.0\"?>");
577
            out.println("<error>");
578
            out.println("Username not specified");
579
            out.println("</error>");
580
            return;
581
        }
582

    
583
        if(params.get("password") == null){
584
            response.setContentType("text/xml");
585
            out.println("<?xml version=\"1.0\"?>");
586
            out.println("<error>");
587
            out.println("Password not specified");
588
            out.println("</error>");
589
            return;
590
        }
591

    
592
        String un = ((String[]) params.get("username"))[0];
593
        MetaCatUtil.debugMessage("user " + un + " try to login", 20);
594
        String pw = ((String[]) params.get("password"))[0];
595

    
596
        String qformat = "xml";
597
        if(params.get("qformat") != null){
598
            qformat = ((String[]) params.get("qformat"))[0];
599
        }
600

    
601
        try {
602
            sess = new AuthSession();
603
        } catch (Exception e) {
604
            System.out.println("error in MetacatServlet.handleLoginAction: "
605
                    + e.getMessage());
606
            out.println(e.getMessage());
607
            return;
608
        }
609
        boolean isValid = sess.authenticate(request, un, pw);
610

    
611
        //if it is authernticate is true, store the session
612
        if (isValid) {
613
            HttpSession session = sess.getSessions();
614
            String id = session.getId();
615
            MetaCatUtil.debugMessage("Store session id " + id
616
                    + "which has username" + session.getAttribute("username")
617
                    + " into hash in login method", 35);
618
            sessionHash.put(id, session);
619
        }
620

    
621
        // format and transform the output
622
        if (qformat.equals("xml")) {
623
            response.setContentType("text/xml");
624
            out.println(sess.getMessage());
625
        } else {
626
            try {
627
                DBTransform trans = new DBTransform();
628
                response.setContentType("text/html");
629
                trans.transformXMLDocument(sess.getMessage(),
630
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
631
                        out, null);
632
            } catch (Exception e) {
633

    
634
                MetaCatUtil.debugMessage(
635
                        "Error in MetaCatServlet.handleLoginAction: "
636
                                + e.getMessage(), 30);
637
            }
638
        }
639
    }
640

    
641
    /**
642
     * Handle the logout request. Close the connection.
643
     */
644
    private void handleLogoutAction(PrintWriter out, Hashtable params,
645
            HttpServletRequest request, HttpServletResponse response)
646
    {
647

    
648
        String qformat = "xml";
649
        if(params.get("qformat") != null){
650
            qformat = ((String[]) params.get("qformat"))[0];
651
        }
652

    
653
        // close the connection
654
        HttpSession sess = request.getSession(false);
655
        MetaCatUtil.debugMessage("After get session in logout request", 40);
656
        if (sess != null) {
657
            MetaCatUtil.debugMessage("The session id " + sess.getId()
658
                    + " will be invalidate in logout action", 30);
659
            MetaCatUtil.debugMessage("The session contains user "
660
                    + sess.getAttribute("username")
661
                    + " will be invalidate in logout action", 30);
662
            sess.invalidate();
663
        }
664

    
665
        // produce output
666
        StringBuffer output = new StringBuffer();
667
        output.append("<?xml version=\"1.0\"?>");
668
        output.append("<logout>");
669
        output.append("User logged out");
670
        output.append("</logout>");
671

    
672
        //format and transform the output
673
        if (qformat.equals("xml")) {
674
            response.setContentType("text/xml");
675
            out.println(output.toString());
676
        } else {
677
            try {
678
                DBTransform trans = new DBTransform();
679
                response.setContentType("text/html");
680
                trans.transformXMLDocument(output.toString(),
681
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
682
                        out, null);
683
            } catch (Exception e) {
684
                MetaCatUtil.debugMessage(
685
                        "Error in MetaCatServlet.handleLogoutAction"
686
                                + e.getMessage(), 30);
687
            }
688
        }
689
    }
690

    
691
    // END OF LOGIN & LOGOUT SECTION
692

    
693
    // SQUERY & QUERY SECTION
694
    /**
695
     * Retreive the squery xml, execute it and display it
696
     *
697
     * @param out the output stream to the client
698
     * @param params the Hashtable of parameters that should be included in the
699
     *            squery.
700
     * @param response the response object linked to the client
701
     * @param conn the database connection
702
     */
703
    protected void handleSQuery(PrintWriter out, Hashtable params,
704
            HttpServletResponse response, String user, String[] groups,
705
            String sessionid)
706
    {
707
        double startTime = System.currentTimeMillis() / 1000;
708
        DBQuery queryobj = new DBQuery(saxparser);
709
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
710
        double outPutTime = System.currentTimeMillis() / 1000;
711
        MetaCatUtil.debugMessage("total search time: "
712
                + (outPutTime - startTime), 30);
713

    
714
    }
715

    
716
    /**
717
     * Create the xml query, execute it and display the results.
718
     *
719
     * @param out the output stream to the client
720
     * @param params the Hashtable of parameters that should be included in the
721
     *            squery.
722
     * @param response the response object linked to the client
723
     */
724
    protected void handleQuery(PrintWriter out, Hashtable params,
725
            HttpServletResponse response, String user, String[] groups,
726
            String sessionid)
727
    {
728
        //create the query and run it
729
        String xmlquery = DBQuery.createSQuery(params);
730
        String[] queryArray = new String[1];
731
        queryArray[0] = xmlquery;
732
        params.put("query", queryArray);
733
        double startTime = System.currentTimeMillis() / 1000;
734
        DBQuery queryobj = new DBQuery(saxparser);
735
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
736
        double outPutTime = System.currentTimeMillis() / 1000;
737
        MetaCatUtil.debugMessage("total search time: "
738
                + (outPutTime - startTime), 30);
739

    
740
        //handleSQuery(out, params, response,user, groups, sessionid);
741
    }
742

    
743
    // END OF SQUERY & QUERY SECTION
744

    
745
    //Exoport section
746
    /**
747
     * Handle the "export" request of data package from Metacat in zip format
748
     *
749
     * @param params the Hashtable of HTTP request parameters
750
     * @param response the HTTP response object linked to the client
751
     * @param user the username sent the request
752
     * @param groups the user's groupnames
753
     */
754
    private void handleExportAction(Hashtable params,
755
            HttpServletResponse response,
756
            String user, String[] groups, String passWord)
757
    {
758
        // Output stream
759
        ServletOutputStream out = null;
760
        // Zip output stream
761
        ZipOutputStream zOut = null;
762
        DocumentImpl docImpls = null;
763
        DBQuery queryObj = null;
764

    
765
        String[] docs = new String[10];
766
        String docId = "";
767

    
768
        try {
769
            // read the params
770
            if (params.containsKey("docid")) {
771
                docs = (String[]) params.get("docid");
772
            }
773
            // Create a DBuery to handle export
774
            queryObj = new DBQuery(saxparser);
775
            // Get the docid
776
            docId = docs[0];
777
            // Make sure the client specify docid
778
            if (docId == null || docId.equals("")) {
779
                response.setContentType("text/xml"); //MIME type
780
                // Get a printwriter
781
                PrintWriter pw = response.getWriter();
782
                // Send back message
783
                pw.println("<?xml version=\"1.0\"?>");
784
                pw.println("<error>");
785
                pw.println("You didn't specify requested docid");
786
                pw.println("</error>");
787
                // Close printwriter
788
                pw.close();
789
                return;
790
            }
791
            // Get output stream
792
            out = response.getOutputStream();
793
            response.setContentType("application/zip"); //MIME type
794
            zOut = new ZipOutputStream(out);
795
            zOut = queryObj
796
                    .getZippedPackage(docId, out, user, groups, passWord);
797
            zOut.finish(); //terminate the zip file
798
            zOut.close(); //close the zip stream
799

    
800
        } catch (Exception e) {
801
            try {
802
                response.setContentType("text/xml"); //MIME type
803
                // Send error message back
804
                if (out != null) {
805
                    PrintWriter pw = new PrintWriter(out);
806
                    pw.println("<?xml version=\"1.0\"?>");
807
                    pw.println("<error>");
808
                    pw.println(e.getMessage());
809
                    pw.println("</error>");
810
                    // Close printwriter
811
                    pw.close();
812
                    // Close output stream
813
                    out.close();
814
                }
815
                // Close zip output stream
816
                if (zOut != null) {
817
                    zOut.close();
818
                }
819
            } catch (IOException ioe) {
820
                MetaCatUtil.debugMessage("Problem with the servlet output "
821
                        + "in MetacatServlet.handleExportAction: "
822
                        + ioe.getMessage(), 30);
823
            }
824

    
825
            MetaCatUtil.debugMessage(
826
                    "Error in MetacatServlet.handleExportAction: "
827
                            + e.getMessage(), 30);
828
            e.printStackTrace(System.out);
829

    
830
        }
831

    
832
    }
833

    
834
    /**
835
     * In eml2 document, the xml can have inline data and data was stripped off
836
     * and store in file system. This action can be used to read inline data
837
     * only
838
     *
839
     * @param params the Hashtable of HTTP request parameters
840
     * @param response the HTTP response object linked to the client
841
     * @param user the username sent the request
842
     * @param groups the user's groupnames
843
     */
844
    private void handleReadInlineDataAction(Hashtable params,
845
            HttpServletRequest request, HttpServletResponse response,
846
            String user, String passWord, String[] groups)
847
    {
848
        String[] docs = new String[10];
849
        String inlineDataId = null;
850
        String docId = "";
851
        ServletOutputStream out = null;
852

    
853
        try {
854
            // read the params
855
            if (params.containsKey("inlinedataid")) {
856
                docs = (String[]) params.get("inlinedataid");
857
            }
858
            // Get the docid
859
            inlineDataId = docs[0];
860
            // Make sure the client specify docid
861
            if (inlineDataId == null || inlineDataId.equals("")) {
862
                throw new Exception("You didn't specify requested inlinedataid"); }
863

    
864
            // check for permission
865
            docId = MetaCatUtil
866
                    .getDocIdWithoutRevFromInlineDataID(inlineDataId);
867
            PermissionController controller = new PermissionController(docId);
868
            // check top level read permission
869
            if (!controller.hasPermission(user, groups,
870
                    AccessControlInterface.READSTRING))
871
            {
872
                throw new Exception("User " + user
873
                        + " doesn't have permission " + " to read document "
874
                        + docId);
875
            }
876
            else
877
            {
878
              //check data access level
879
              try
880
              {
881
                Hashtable unReadableInlineDataList =
882
                    PermissionController.getUnReadableInlineDataIdList(docId,
883
                    user, groups, false);
884
                if (unReadableInlineDataList.containsValue(
885
                          MetaCatUtil.getInlineDataIdWithoutRev(inlineDataId)))
886
                {
887
                  throw new Exception("User " + user
888
                       + " doesn't have permission " + " to read inlinedata "
889
                       + inlineDataId);
890

    
891
                }//if
892
              }//try
893
              catch (Exception e)
894
              {
895
                throw e;
896
              }//catch
897
            }//else
898

    
899
            // Get output stream
900
            out = response.getOutputStream();
901
            // read the inline data from the file
902
            String inlinePath = MetaCatUtil.getOption("inlinedatafilepath");
903
            File lineData = new File(inlinePath, inlineDataId);
904
            FileInputStream input = new FileInputStream(lineData);
905
            byte[] buffer = new byte[4 * 1024];
906
            int bytes = input.read(buffer);
907
            while (bytes != -1) {
908
                out.write(buffer, 0, bytes);
909
                bytes = input.read(buffer);
910
            }
911
            out.close();
912

    
913
            EventLog.getInstance().log(request.getRemoteAddr(), user,
914
                    inlineDataId, "readinlinedata");
915
        } catch (Exception e) {
916
            try {
917
                PrintWriter pw = null;
918
                // Send error message back
919
                if (out != null) {
920
                    pw = new PrintWriter(out);
921
                } else {
922
                    pw = response.getWriter();
923
                }
924
                pw.println("<?xml version=\"1.0\"?>");
925
                pw.println("<error>");
926
                pw.println(e.getMessage());
927
                pw.println("</error>");
928
                // Close printwriter
929
                pw.close();
930
                // Close output stream if out is not null
931
                if (out != null) {
932
                    out.close();
933
                }
934
            } catch (IOException ioe) {
935
                MetaCatUtil.debugMessage("Problem with the servlet output "
936
                        + "in MetacatServlet.handleExportAction: "
937
                        + ioe.getMessage(), 30);
938
            }
939
            MetaCatUtil.debugMessage(
940
                    "Error in MetacatServlet.handleReadInlineDataAction: "
941
                            + e.getMessage(), 30);
942
        }
943
    }
944

    
945
    /*
946
     * Get the nodeid from xml_nodes for the inlinedataid
947
     */
948
    private long getInlineDataNodeId(String inLineDataId, String docId)
949
            throws SQLException
950
    {
951
        long nodeId = 0;
952
        String INLINE = "inline";
953
        boolean hasRow;
954
        PreparedStatement pStmt = null;
955
        DBConnection conn = null;
956
        int serialNumber = -1;
957
        String sql = "SELECT nodeid FROM xml_nodes WHERE docid=? AND nodedata=? "
958
                + "AND nodetype='TEXT' AND parentnodeid IN "
959
                + "(SELECT nodeid FROM xml_nodes WHERE docid=? AND "
960
                + "nodetype='ELEMENT' AND nodename='" + INLINE + "')";
961

    
962
        try {
963
            //check out DBConnection
964
            conn = DBConnectionPool
965
                    .getDBConnection("AccessControlList.isAllowFirst");
966
            serialNumber = conn.getCheckOutSerialNumber();
967

    
968
            pStmt = conn.prepareStatement(sql);
969
            //bind value
970
            pStmt.setString(1, docId);//docid
971
            pStmt.setString(2, inLineDataId);//inlinedataid
972
            pStmt.setString(3, docId);
973
            // excute query
974
            pStmt.execute();
975
            ResultSet rs = pStmt.getResultSet();
976
            hasRow = rs.next();
977
            // get result
978
            if (hasRow) {
979
                nodeId = rs.getLong(1);
980
            }//if
981

    
982
        } catch (SQLException e) {
983
            throw e;
984
        } finally {
985
            try {
986
                pStmt.close();
987
            } finally {
988
                DBConnectionPool.returnDBConnection(conn, serialNumber);
989
            }
990
        }
991
        MetaCatUtil.debugMessage("The nodeid for inlinedataid " + inLineDataId
992
                + " is: " + nodeId, 35);
993
        return nodeId;
994
    }
995

    
996
    /**
997
     * Handle the "read" request of metadata/data files from Metacat or any
998
     * files from Internet; transformed metadata XML document into HTML
999
     * presentation if requested; zip files when more than one were requested.
1000
     *
1001
     * @param params the Hashtable of HTTP request parameters
1002
     * @param request the HTTP request object linked to the client
1003
     * @param response the HTTP response object linked to the client
1004
     * @param user the username sent the request
1005
     * @param groups the user's groupnames
1006
     */
1007
    private void handleReadAction(Hashtable params, HttpServletRequest request,
1008
            HttpServletResponse response, String user, String passWord,
1009
            String[] groups)
1010
    {
1011
        ServletOutputStream out = null;
1012
        ZipOutputStream zout = null;
1013
        PrintWriter pw = null;
1014
        boolean zip = false;
1015
        boolean withInlineData = true;
1016

    
1017
        try {
1018
            String[] docs = new String[0];
1019
            String docid = "";
1020
            String qformat = "";
1021
            String abstrpath = null;
1022

    
1023
            // read the params
1024
            if (params.containsKey("docid")) {
1025
                docs = (String[]) params.get("docid");
1026
            }
1027
            if (params.containsKey("qformat")) {
1028
                qformat = ((String[]) params.get("qformat"))[0];
1029
            }
1030
            // the param for only metadata (eml)
1031
            // we don't support read a eml document without inline data now.
1032
            /*if (params.containsKey("inlinedata")) {
1033

    
1034
                String inlineData = ((String[]) params.get("inlinedata"))[0];
1035
                if (inlineData.equalsIgnoreCase("false")) {
1036
                    withInlineData = false;
1037
                }
1038
            }*/
1039
            if ((docs.length > 1) || qformat.equals("zip")) {
1040
                zip = true;
1041
                out = response.getOutputStream();
1042
                response.setContentType("application/zip"); //MIME type
1043
                zout = new ZipOutputStream(out);
1044
            }
1045
            // go through the list of docs to read
1046
            for (int i = 0; i < docs.length; i++) {
1047
                try {
1048

    
1049
                    URL murl = new URL(docs[i]);
1050
                    Hashtable murlQueryStr = MetaCatUtil.parseQuery(
1051
                            murl.getQuery());
1052
                    // case docid="http://.../?docid=aaa"
1053
                    // or docid="metacat://.../?docid=bbb"
1054
                    if (murlQueryStr.containsKey("docid")) {
1055
                        // get only docid, eliminate the rest
1056
                        docid = (String) murlQueryStr.get("docid");
1057
                        if (zip) {
1058
                            addDocToZip(request, docid, zout, user, groups);
1059
                        } else {
1060
                            readFromMetacat(request, response, docid, qformat,
1061
                                    abstrpath, user, groups, zip, zout,
1062
                                    withInlineData, params);
1063
                        }
1064

    
1065
                        // case docid="http://.../filename"
1066
                    } else {
1067
                        docid = docs[i];
1068
                        if (zip) {
1069
                            addDocToZip(request, docid, zout, user, groups);
1070
                        } else {
1071
                            readFromURLConnection(response, docid);
1072
                        }
1073
                    }
1074

    
1075
                } catch (MalformedURLException mue) {
1076
                    docid = docs[i];
1077
                    if (zip) {
1078
                        addDocToZip(request, docid, zout, user, groups);
1079
                    } else {
1080
                        readFromMetacat(request, response, docid, qformat,
1081
                                abstrpath, user, groups, zip, zout,
1082
                                withInlineData, params);
1083
                    }
1084
                }
1085
            }
1086

    
1087
            if (zip) {
1088
                zout.finish(); //terminate the zip file
1089
                zout.close(); //close the zip stream
1090
            }
1091

    
1092
        } catch (McdbDocNotFoundException notFoundE) {
1093
            // To handle doc not found exception
1094
            // the docid which didn't be found
1095
            String notFoundDocId = notFoundE.getUnfoundDocId();
1096
            String notFoundRevision = notFoundE.getUnfoundRevision();
1097
            MetaCatUtil.debugMessage("Missed id: " + notFoundDocId, 30);
1098
            MetaCatUtil.debugMessage("Missed rev: " + notFoundRevision, 30);
1099
            try {
1100
                // read docid from remote server
1101
                readFromRemoteMetaCat(response, notFoundDocId,
1102
                        notFoundRevision, user, passWord, out, zip, zout);
1103
                // Close zout outputstream
1104
                if (zout != null) {
1105
                    zout.close();
1106
                }
1107
                // close output stream
1108
                if (out != null) {
1109
                    out.close();
1110
                }
1111

    
1112
            } catch (Exception exc) {
1113
                MetaCatUtil.debugMessage(
1114
                        "Erorr in MetacatServlet.hanldReadAction: "
1115
                                + exc.getMessage(), 30);
1116
                try {
1117
                    if (out != null) {
1118
                        response.setContentType("text/xml");
1119
                        // Send back error message by printWriter
1120
                        pw = new PrintWriter(out);
1121
                        pw.println("<?xml version=\"1.0\"?>");
1122
                        pw.println("<error>");
1123
                        pw.println(notFoundE.getMessage());
1124
                        pw.println("</error>");
1125
                        pw.close();
1126
                        out.close();
1127

    
1128
                    } else {
1129
                        response.setContentType("text/xml"); //MIME type
1130
                        // Send back error message if out = null
1131
                        if (pw == null) {
1132
                            // If pw is null, open the respnose
1133
                            pw = response.getWriter();
1134
                        }
1135
                        pw.println("<?xml version=\"1.0\"?>");
1136
                        pw.println("<error>");
1137
                        pw.println(notFoundE.getMessage());
1138
                        pw.println("</error>");
1139
                        pw.close();
1140
                    }
1141
                    // close zout
1142
                    if (zout != null) {
1143
                        zout.close();
1144
                    }
1145
                } catch (IOException ie) {
1146
                    MetaCatUtil.debugMessage("Problem with the servlet output "
1147
                            + "in MetacatServlet.handleReadAction: "
1148
                            + ie.getMessage(), 30);
1149
                }
1150
            }
1151
        } catch (Exception e) {
1152
            try {
1153

    
1154
                if (out != null) {
1155
                    response.setContentType("text/xml"); //MIME type
1156
                    pw = new PrintWriter(out);
1157
                    pw.println("<?xml version=\"1.0\"?>");
1158
                    pw.println("<error>");
1159
                    pw.println(e.getMessage());
1160
                    pw.println("</error>");
1161
                    pw.close();
1162
                    out.close();
1163
                } else {
1164
                    response.setContentType("text/xml"); //MIME type
1165
                    // Send back error message if out = null
1166
                    if (pw == null) {
1167
                        pw = response.getWriter();
1168
                    }
1169
                    pw.println("<?xml version=\"1.0\"?>");
1170
                    pw.println("<error>");
1171
                    pw.println(e.getMessage());
1172
                    pw.println("</error>");
1173
                    pw.close();
1174

    
1175
                }
1176
                // Close zip output stream
1177
                if (zout != null) {
1178
                    zout.close();
1179
                }
1180

    
1181
            } catch (IOException ioe) {
1182
                MetaCatUtil.debugMessage("Problem with the servlet output "
1183
                        + "in MetacatServlet.handleReadAction: "
1184
                        + ioe.getMessage(), 30);
1185
                ioe.printStackTrace(System.out);
1186

    
1187
            }
1188

    
1189
            MetaCatUtil.debugMessage(
1190
                    "Error in MetacatServlet.handleReadAction: "
1191
                            + e.getMessage(), 30);
1192
            //e.printStackTrace(System.out);
1193
        }
1194
    }
1195

    
1196
    /** read metadata or data from Metacat
1197
     */
1198
    private void readFromMetacat(HttpServletRequest request,
1199
            HttpServletResponse response, String docid, String qformat,
1200
            String abstrpath, String user, String[] groups, boolean zip,
1201
            ZipOutputStream zout, boolean withInlineData, Hashtable params)
1202
            throws ClassNotFoundException, IOException, SQLException,
1203
            McdbException, Exception
1204
    {
1205

    
1206
        try {
1207

    
1208
            DocumentImpl doc = new DocumentImpl(docid);
1209

    
1210
            //check the permission for read
1211
            if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1212
                Exception e = new Exception("User " + user
1213
                        + " does not have permission"
1214
                        + " to read the document with the docid " + docid);
1215

    
1216
                throw e;
1217
            }
1218

    
1219
            if (doc.getRootNodeID() == 0) {
1220
                // this is data file
1221
                String filepath = MetaCatUtil.getOption("datafilepath");
1222
                if (!filepath.endsWith("/")) {
1223
                    filepath += "/";
1224
                }
1225
                String filename = filepath + docid;
1226
                FileInputStream fin = null;
1227
                fin = new FileInputStream(filename);
1228

    
1229
                //MIME type
1230
                String contentType = getServletContext().getMimeType(filename);
1231
                if (contentType == null) {
1232
                    ContentTypeProvider provider = new ContentTypeProvider(
1233
                            docid);
1234
                    contentType = provider.getContentType();
1235
                    MetaCatUtil.debugMessage("Final contenttype is: "
1236
                            + contentType, 30);
1237
                }
1238

    
1239
                response.setContentType(contentType);
1240
                // if we decide to use "application/octet-stream" for all data
1241
                // returns
1242
                // response.setContentType("application/octet-stream");
1243

    
1244
                try {
1245

    
1246
                    ServletOutputStream out = response.getOutputStream();
1247
                    byte[] buf = new byte[4 * 1024]; // 4K buffer
1248
                    int b = fin.read(buf);
1249
                    while (b != -1) {
1250
                        out.write(buf, 0, b);
1251
                        b = fin.read(buf);
1252
                    }
1253
                } finally {
1254
                    if (fin != null) fin.close();
1255
                }
1256

    
1257
            } else {
1258
                // this is metadata doc
1259
                if (qformat.equals("xml") || qformat.equals("")) {
1260
                    // if equals "", that means no qformat is specified. hence
1261
                    // by default the document should be returned in xml format
1262
                    // set content type first
1263
                    response.setContentType("text/xml"); //MIME type
1264
                    PrintWriter out = response.getWriter();
1265
                    doc.toXml(out, user, groups, withInlineData);
1266
                } else {
1267
                    response.setContentType("text/html"); //MIME type
1268
                    PrintWriter out = response.getWriter();
1269

    
1270
                    // Look up the document type
1271
                    String doctype = doc.getDoctype();
1272
                    // Transform the document to the new doctype
1273
                    DBTransform dbt = new DBTransform();
1274
                    dbt.transformXMLDocument(doc.toString(user, groups,
1275
                            withInlineData), doctype, "-//W3C//HTML//EN",
1276
                            qformat, out, params);
1277
                }
1278

    
1279
            }
1280
            EventLog.getInstance().log(request.getRemoteAddr(), user,
1281
                    docid, "read");
1282
        } catch (Exception except) {
1283
            throw except;
1284
        }
1285
    }
1286

    
1287
    /**
1288
     * read data from URLConnection
1289
     */
1290
    private void readFromURLConnection(HttpServletResponse response,
1291
            String docid) throws IOException, MalformedURLException
1292
    {
1293
        ServletOutputStream out = response.getOutputStream();
1294
        String contentType = getServletContext().getMimeType(docid); //MIME
1295
                                                                     // type
1296
        if (contentType == null) {
1297
            if (docid.endsWith(".xml")) {
1298
                contentType = "text/xml";
1299
            } else if (docid.endsWith(".css")) {
1300
                contentType = "text/css";
1301
            } else if (docid.endsWith(".dtd")) {
1302
                contentType = "text/plain";
1303
            } else if (docid.endsWith(".xsd")) {
1304
                contentType = "text/xml";
1305
            } else if (docid.endsWith("/")) {
1306
                contentType = "text/html";
1307
            } else {
1308
                File f = new File(docid);
1309
                if (f.isDirectory()) {
1310
                    contentType = "text/html";
1311
                } else {
1312
                    contentType = "application/octet-stream";
1313
                }
1314
            }
1315
        }
1316
        response.setContentType(contentType);
1317
        // if we decide to use "application/octet-stream" for all data returns
1318
        // response.setContentType("application/octet-stream");
1319

    
1320
        // this is http url
1321
        URL url = new URL(docid);
1322
        BufferedInputStream bis = null;
1323
        try {
1324
            bis = new BufferedInputStream(url.openStream());
1325
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1326
            int b = bis.read(buf);
1327
            while (b != -1) {
1328
                out.write(buf, 0, b);
1329
                b = bis.read(buf);
1330
            }
1331
        } finally {
1332
            if (bis != null) bis.close();
1333
        }
1334

    
1335
    }
1336

    
1337
    /**
1338
     * read file/doc and write to ZipOutputStream
1339
     *
1340
     * @param docid
1341
     * @param zout
1342
     * @param user
1343
     * @param groups
1344
     * @throws ClassNotFoundException
1345
     * @throws IOException
1346
     * @throws SQLException
1347
     * @throws McdbException
1348
     * @throws Exception
1349
     */
1350
    private void addDocToZip(HttpServletRequest request, String docid,
1351
            ZipOutputStream zout, String user, String[] groups) throws
1352
            ClassNotFoundException, IOException, SQLException, McdbException,
1353
            Exception
1354
    {
1355
        byte[] bytestring = null;
1356
        ZipEntry zentry = null;
1357

    
1358
        try {
1359
            URL url = new URL(docid);
1360

    
1361
            // this http url; read from URLConnection; add to zip
1362
            zentry = new ZipEntry(docid);
1363
            zout.putNextEntry(zentry);
1364
            BufferedInputStream bis = null;
1365
            try {
1366
                bis = new BufferedInputStream(url.openStream());
1367
                byte[] buf = new byte[4 * 1024]; // 4K buffer
1368
                int b = bis.read(buf);
1369
                while (b != -1) {
1370
                    zout.write(buf, 0, b);
1371
                    b = bis.read(buf);
1372
                }
1373
            } finally {
1374
                if (bis != null) bis.close();
1375
            }
1376
            zout.closeEntry();
1377

    
1378
        } catch (MalformedURLException mue) {
1379

    
1380
            // this is metacat doc (data file or metadata doc)
1381
            try {
1382
                DocumentImpl doc = new DocumentImpl(docid);
1383

    
1384
                //check the permission for read
1385
                if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1386
                    Exception e = new Exception("User " + user
1387
                            + " does not have "
1388
                            + "permission to read the document with the docid "
1389
                            + docid);
1390
                    throw e;
1391
                }
1392

    
1393
                if (doc.getRootNodeID() == 0) {
1394
                    // this is data file; add file to zip
1395
                    String filepath = MetaCatUtil.getOption("datafilepath");
1396
                    if (!filepath.endsWith("/")) {
1397
                        filepath += "/";
1398
                    }
1399
                    String filename = filepath + docid;
1400
                    FileInputStream fin = null;
1401
                    fin = new FileInputStream(filename);
1402
                    try {
1403

    
1404
                        zentry = new ZipEntry(docid);
1405
                        zout.putNextEntry(zentry);
1406
                        byte[] buf = new byte[4 * 1024]; // 4K buffer
1407
                        int b = fin.read(buf);
1408
                        while (b != -1) {
1409
                            zout.write(buf, 0, b);
1410
                            b = fin.read(buf);
1411
                        }
1412
                    } finally {
1413
                        if (fin != null) fin.close();
1414
                    }
1415
                    zout.closeEntry();
1416

    
1417
                } else {
1418
                    // this is metadata doc; add doc to zip
1419
                    bytestring = doc.toString().getBytes();
1420
                    zentry = new ZipEntry(docid + ".xml");
1421
                    zentry.setSize(bytestring.length);
1422
                    zout.putNextEntry(zentry);
1423
                    zout.write(bytestring, 0, bytestring.length);
1424
                    zout.closeEntry();
1425
                }
1426
                EventLog.getInstance().log(request.getRemoteAddr(), user,
1427
                        docid, "read");
1428
            } catch (Exception except) {
1429
                throw except;
1430
            }
1431
        }
1432
    }
1433

    
1434
    /**
1435
     * If metacat couldn't find a data file or document locally, it will read
1436
     * this docid from its home server. This is for the replication feature
1437
     */
1438
    private void readFromRemoteMetaCat(HttpServletResponse response,
1439
            String docid, String rev, String user, String password,
1440
            ServletOutputStream out, boolean zip, ZipOutputStream zout)
1441
            throws Exception
1442
    {
1443
        // Create a object of RemoteDocument, "" is for zipEntryPath
1444
        RemoteDocument remoteDoc = new RemoteDocument(docid, rev, user,
1445
                password, "");
1446
        String docType = remoteDoc.getDocType();
1447
        // Only read data file
1448
        if (docType.equals("BIN")) {
1449
            // If it is zip format
1450
            if (zip) {
1451
                remoteDoc.readDocumentFromRemoteServerByZip(zout);
1452
            } else {
1453
                if (out == null) {
1454
                    out = response.getOutputStream();
1455
                }
1456
                response.setContentType("application/octet-stream");
1457
                remoteDoc.readDocumentFromRemoteServer(out);
1458
            }
1459
        } else {
1460
            throw new Exception("Docid: " + docid + "." + rev
1461
                    + " couldn't find");
1462
        }
1463
    }
1464

    
1465
    /**
1466
     * Handle the database putdocument request and write an XML document to the
1467
     * database connection
1468
     */
1469
    private void handleInsertOrUpdateAction(HttpServletRequest request,
1470
            HttpServletResponse response, PrintWriter out, Hashtable params,
1471
            String user, String[] groups)
1472
    {
1473
        DBConnection dbConn = null;
1474
        int serialNumber = -1;
1475

    
1476
        if(params.get("docid") == null){
1477
            out.println("<?xml version=\"1.0\"?>");
1478
            out.println("<error>");
1479
            out.println("Docid not specified");
1480
            out.println("</error>");
1481
            return;
1482
        }
1483

    
1484
        try {
1485
            // Get the document indicated
1486
            String[] doctext = (String[]) params.get("doctext");
1487

    
1488
            String pub = null;
1489
            if (params.containsKey("public")) {
1490
                pub = ((String[]) params.get("public"))[0];
1491
            }
1492

    
1493
            StringReader dtd = null;
1494
            if (params.containsKey("dtdtext")) {
1495
                String[] dtdtext = (String[]) params.get("dtdtext");
1496
                try {
1497
                    if (!dtdtext[0].equals("")) {
1498
                        dtd = new StringReader(dtdtext[0]);
1499
                    }
1500
                } catch (NullPointerException npe) {
1501
                }
1502
            }
1503
            StringReader xml = new StringReader(doctext[0]);
1504
            boolean validate = false;
1505
            DocumentImplWrapper documentWrapper = null;
1506
            try {
1507
                // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ...
1508
                // >
1509
                // in order to decide whether to use validation parser
1510
                validate = needDTDValidation(xml);
1511
                if (validate) {
1512
                    // set a dtd base validation parser
1513
                    String rule = DocumentImpl.DTD;
1514
                    documentWrapper = new DocumentImplWrapper(rule, validate);
1515
                } else if (needSchemaValidation(xml)) {
1516
                    // for eml2
1517
                    String namespace = findNamespace(xml);
1518
                    if (namespace.compareTo(DocumentImpl.EML2_0_0NAMESPACE) == 0
1519
                                || namespace.compareTo(
1520
                                DocumentImpl.EML2_0_1NAMESPACE) == 0) {
1521
                        // set eml2 base validation parser
1522
                        String rule = DocumentImpl.EML200;
1523
                        // using emlparser to check id validation
1524
                        EMLParser parser = new EMLParser(doctext[0]);
1525
                        documentWrapper = new DocumentImplWrapper(rule, true);
1526
                    } else if (namespace.compareTo(
1527
                                DocumentImpl.EML2_1_0NAMESPACE) == 0) {
1528
                        // set eml2 base validation parser
1529
                        String rule = DocumentImpl.EML210;
1530
                        // using emlparser to check id validation
1531
                        EMLParser parser = new EMLParser(doctext[0]);
1532
                        documentWrapper = new DocumentImplWrapper(rule, true);
1533
                    } else {
1534
                        // set schema base validation parser
1535
                        String rule = DocumentImpl.SCHEMA;
1536
                        documentWrapper = new DocumentImplWrapper(rule, true);
1537
                    }
1538
                } else {
1539
                    documentWrapper = new DocumentImplWrapper("", false);
1540
                }
1541

    
1542
                String[] action = (String[]) params.get("action");
1543
                String[] docid = (String[]) params.get("docid");
1544
                String newdocid = null;
1545

    
1546
                String doAction = null;
1547
                if (action[0].equals("insert")) {
1548
                    doAction = "INSERT";
1549
                } else if (action[0].equals("update")) {
1550
                    doAction = "UPDATE";
1551
                }
1552

    
1553
                try {
1554
                    // get a connection from the pool
1555
                    dbConn = DBConnectionPool
1556
                            .getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1557
                    serialNumber = dbConn.getCheckOutSerialNumber();
1558

    
1559
                    // write the document to the database
1560
                    try {
1561
                        String accNumber = docid[0];
1562
                        MetaCatUtil.debugMessage("" + doAction + " "
1563
                                + accNumber + "...", 10);
1564
                        if (accNumber.equals("")) {
1565
                            accNumber = null;
1566
                        }
1567
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1568
                                doAction, accNumber, user, groups);
1569
                        EventLog.getInstance().log(request.getRemoteAddr(),
1570
                                user, accNumber, action[0]);
1571
                    } catch (NullPointerException npe) {
1572
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1573
                                doAction, null, user, groups);
1574
                        EventLog.getInstance().log(request.getRemoteAddr(),
1575
                                user, "", action[0]);
1576
                    }
1577
                }
1578
                finally {
1579
                    // Return db connection
1580
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1581
                }
1582

    
1583
                // set content type and other response header fields first
1584
                //response.setContentType("text/xml");
1585
                out.println("<?xml version=\"1.0\"?>");
1586
                out.println("<success>");
1587
                out.println("<docid>" + newdocid + "</docid>");
1588
                out.println("</success>");
1589

    
1590
            } catch (NullPointerException npe) {
1591
                //response.setContentType("text/xml");
1592
                out.println("<?xml version=\"1.0\"?>");
1593
                out.println("<error>");
1594
                out.println(npe.getMessage());
1595
                out.println("</error>");
1596
            }
1597
        } catch (Exception e) {
1598
            //response.setContentType("text/xml");
1599
            out.println("<?xml version=\"1.0\"?>");
1600
            out.println("<error>");
1601
            out.println(e.getMessage());
1602
            out.println("</error>");
1603
        }
1604
    }
1605

    
1606
    /**
1607
     * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > in
1608
     * order to decide whether to use validation parser
1609
     */
1610
    private static boolean needDTDValidation(StringReader xmlreader)
1611
            throws IOException
1612
    {
1613

    
1614
        StringBuffer cbuff = new StringBuffer();
1615
        java.util.Stack st = new java.util.Stack();
1616
        boolean validate = false;
1617
        int c;
1618
        int inx;
1619

    
1620
        // read from the stream until find the keywords
1621
        while ((st.empty() || st.size() < 4) && ((c = xmlreader.read()) != -1)) {
1622
            cbuff.append((char) c);
1623

    
1624
            // "<!DOCTYPE" keyword is found; put it in the stack
1625
            if ((inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1) {
1626
                cbuff = new StringBuffer();
1627
                st.push("<!DOCTYPE");
1628
            }
1629
            // "PUBLIC" keyword is found; put it in the stack
1630
            if ((inx = cbuff.toString().indexOf("PUBLIC")) != -1) {
1631
                cbuff = new StringBuffer();
1632
                st.push("PUBLIC");
1633
            }
1634
            // "SYSTEM" keyword is found; put it in the stack
1635
            if ((inx = cbuff.toString().indexOf("SYSTEM")) != -1) {
1636
                cbuff = new StringBuffer();
1637
                st.push("SYSTEM");
1638
            }
1639
            // ">" character is found; put it in the stack
1640
            // ">" is found twice: fisrt from <?xml ...?>
1641
            // and second from <!DOCTYPE ... >
1642
            if ((inx = cbuff.toString().indexOf(">")) != -1) {
1643
                cbuff = new StringBuffer();
1644
                st.push(">");
1645
            }
1646
        }
1647

    
1648
        // close the stream
1649
        xmlreader.reset();
1650

    
1651
        // check the stack whether it contains the keywords:
1652
        // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1653
        if (st.size() == 4) {
1654
            if (((String) st.pop()).equals(">")
1655
                    && (((String) st.peek()).equals("PUBLIC") | ((String) st
1656
                            .pop()).equals("SYSTEM"))
1657
                    && ((String) st.pop()).equals("<!DOCTYPE")) {
1658
                validate = true;
1659
            }
1660
        }
1661

    
1662
        MetaCatUtil.debugMessage("Validation for dtd is " + validate, 10);
1663
        return validate;
1664
    }
1665

    
1666
    // END OF INSERT/UPDATE SECTION
1667

    
1668
    /* check if the xml string contains key words to specify schema loocation */
1669
    private boolean needSchemaValidation(StringReader xml) throws IOException
1670
    {
1671
        boolean needSchemaValidate = false;
1672
        if (xml == null) {
1673
            MetaCatUtil.debugMessage("Validation for schema is "
1674
                    + needSchemaValidate, 10);
1675
            return needSchemaValidate;
1676
        }
1677
        System.out.println("before get target line");
1678
        String targetLine = getSchemaLine(xml);
1679
        System.out.println("after get target line");
1680
        // to see if the second line contain some keywords
1681
        if (targetLine != null
1682
                && (targetLine.indexOf(SCHEMALOCATIONKEYWORD) != -1 || targetLine
1683
                        .indexOf(NONAMESPACELOCATION) != -1)) {
1684
            // if contains schema location key word, should be validate
1685
            needSchemaValidate = true;
1686
        }
1687

    
1688
        MetaCatUtil.debugMessage("Validation for schema is "
1689
                + needSchemaValidate, 10);
1690
        return needSchemaValidate;
1691

    
1692
    }
1693

    
1694
    /* check if the xml string contains key words to specify schema loocation */
1695
    private String findNamespace(StringReader xml) throws IOException
1696
    {
1697
        String namespace = null;
1698

    
1699
        String eml2_0_0NameSpace = DocumentImpl.EML2_0_0NAMESPACE;
1700
        String eml2_0_1NameSpace = DocumentImpl.EML2_0_1NAMESPACE;
1701
        String eml2_1_0NameSpace = DocumentImpl.EML2_1_0NAMESPACE;
1702

    
1703
        if (xml == null) {
1704
            MetaCatUtil.debugMessage("Validation for schema is "
1705
                    + namespace, 10);
1706
            return namespace;
1707
        }
1708
        String targetLine = getSchemaLine(xml);
1709

    
1710
        if (targetLine != null) {
1711

    
1712
            int startIndex = targetLine.indexOf(SCHEMALOCATIONKEYWORD);
1713
            int start = 1;
1714
            int end = 1;
1715
            String schemaLocation = null;
1716
            int count = 0;
1717
            if (startIndex != -1) {
1718
                for (int i = startIndex; i < targetLine.length(); i++) {
1719
                    if (targetLine.charAt(i) == '"') {
1720
                        count++;
1721
                    }
1722
                    if (targetLine.charAt(i) == '"' && count == 1) {
1723
                        start = i;
1724
                    }
1725
                    if (targetLine.charAt(i) == '"' && count == 2) {
1726
                        end = i;
1727
                        break;
1728
                    }
1729
                }
1730
            }
1731
            schemaLocation = targetLine.substring(start + 1, end);
1732
            MetaCatUtil.debugMessage("schemaLocation in xml is: "
1733
                    + schemaLocation, 30);
1734
            if (schemaLocation.indexOf(eml2_0_0NameSpace) != -1) {
1735
                namespace = eml2_0_0NameSpace;
1736
            } else if (schemaLocation.indexOf(eml2_0_1NameSpace) != -1) {
1737
                namespace = eml2_0_1NameSpace;
1738
            } else if (schemaLocation.indexOf(eml2_1_0NameSpace) != -1) {
1739
                namespace = eml2_1_0NameSpace;
1740
            }
1741
        }
1742

    
1743
        MetaCatUtil.debugMessage("Validation for eml is " + namespace,
1744
                10);
1745

    
1746
        return namespace;
1747

    
1748
    }
1749

    
1750
    private String getSchemaLine(StringReader xml) throws IOException
1751
    {
1752
        // find the line
1753
        String secondLine = null;
1754
        int count = 0;
1755
        int endIndex = 0;
1756
        int startIndex = 0;
1757
        final int TARGETNUM = 2;
1758
        StringBuffer buffer = new StringBuffer();
1759
        boolean comment = false;
1760
        char thirdPreviousCharacter = '?';
1761
        char secondPreviousCharacter = '?';
1762
        char previousCharacter = '?';
1763
        char currentCharacter = '?';
1764
        int tmp = xml.read();
1765
        while (tmp != -1) {
1766
            currentCharacter = (char)tmp;
1767
            //in a comment
1768
            if (currentCharacter == '-' && previousCharacter == '-'
1769
                    && secondPreviousCharacter == '!'
1770
                    && thirdPreviousCharacter == '<') {
1771
                comment = true;
1772
            }
1773
            //out of comment
1774
            if (comment && currentCharacter == '>' && previousCharacter == '-'
1775
                    && secondPreviousCharacter == '-') {
1776
                comment = false;
1777
            }
1778

    
1779
            //this is not comment
1780
            if (currentCharacter != '!' && previousCharacter == '<' && !comment) {
1781
                count++;
1782
            }
1783
            // get target line
1784
            if (count == TARGETNUM && currentCharacter != '>') {
1785
                buffer.append(currentCharacter);
1786
            }
1787
            if (count == TARGETNUM && currentCharacter == '>') {
1788
                break;
1789
            }
1790
            thirdPreviousCharacter = secondPreviousCharacter;
1791
            secondPreviousCharacter = previousCharacter;
1792
            previousCharacter = currentCharacter;
1793
            tmp = xml.read();
1794
        }
1795
        secondLine = buffer.toString();
1796
        MetaCatUtil
1797
                .debugMessage("the second line string is: " + secondLine, 25);
1798
        xml.reset();
1799
        return secondLine;
1800
    }
1801

    
1802
    /**
1803
     * Handle the database delete request and delete an XML document from the
1804
     * database connection
1805
     */
1806
    private void handleDeleteAction(PrintWriter out, Hashtable params,
1807
            HttpServletRequest request, HttpServletResponse response,
1808
            String user, String[] groups)
1809
    {
1810

    
1811
        String[] docid = (String[]) params.get("docid");
1812

    
1813
        if(docid == null){
1814
          response.setContentType("text/xml");
1815
          out.println("<?xml version=\"1.0\"?>");
1816
          out.println("<error>");
1817
          out.println("Docid not specified.");
1818
          out.println("</error>");
1819
        } else {
1820

    
1821
            // delete the document from the database
1822
            try {
1823

    
1824
                try {
1825
                    DocumentImpl.delete(docid[0], user, groups);
1826
                    EventLog.getInstance().log(request.getRemoteAddr(),
1827
                                               user, docid[0], "delete");
1828
                    response.setContentType("text/xml");
1829
                    out.println("<?xml version=\"1.0\"?>");
1830
                    out.println("<success>");
1831
                    out.println("Document deleted.");
1832
                    out.println("</success>");
1833
                }
1834
                catch (AccessionNumberException ane) {
1835
                    response.setContentType("text/xml");
1836
                    out.println("<?xml version=\"1.0\"?>");
1837
                    out.println("<error>");
1838
                    //out.println("Error deleting document!!!");
1839
                    out.println(ane.getMessage());
1840
                    out.println("</error>");
1841
                }
1842
            }
1843
            catch (Exception e) {
1844
                response.setContentType("text/xml");
1845
                out.println("<?xml version=\"1.0\"?>");
1846
                out.println("<error>");
1847
                out.println(e.getMessage());
1848
                out.println("</error>");
1849
            }
1850
        }
1851
    }
1852

    
1853
    /**
1854
     * Handle the validation request and return the results to the requestor
1855
     */
1856
    private void handleValidateAction(PrintWriter out, Hashtable params)
1857
    {
1858

    
1859
        // Get the document indicated
1860
        String valtext = null;
1861
        DBConnection dbConn = null;
1862
        int serialNumber = -1;
1863

    
1864
        try {
1865
            valtext = ((String[]) params.get("valtext"))[0];
1866
        } catch (Exception nullpe) {
1867

    
1868
            String docid = null;
1869
            try {
1870
                // Find the document id number
1871
                docid = ((String[]) params.get("docid"))[0];
1872

    
1873
                // Get the document indicated from the db
1874
                DocumentImpl xmldoc = new DocumentImpl(docid);
1875
                valtext = xmldoc.toString();
1876

    
1877
            } catch (NullPointerException npe) {
1878

    
1879
                out.println("<error>Error getting document ID: " + docid
1880
                        + "</error>");
1881
                //if ( conn != null ) { util.returnConnection(conn); }
1882
                return;
1883
            } catch (Exception e) {
1884

    
1885
                out.println(e.getMessage());
1886
            }
1887
        }
1888

    
1889
        try {
1890
            // get a connection from the pool
1891
            dbConn = DBConnectionPool
1892
                    .getDBConnection("MetaCatServlet.handleValidateAction");
1893
            serialNumber = dbConn.getCheckOutSerialNumber();
1894
            DBValidate valobj = new DBValidate(saxparser, dbConn);
1895
            boolean valid = valobj.validateString(valtext);
1896

    
1897
            // set content type and other response header fields first
1898

    
1899
            out.println(valobj.returnErrors());
1900

    
1901
        } catch (NullPointerException npe2) {
1902
            // set content type and other response header fields first
1903

    
1904
            out.println("<error>Error validating document.</error>");
1905
        } catch (Exception e) {
1906

    
1907
            out.println(e.getMessage());
1908
        } finally {
1909
            // Return db connection
1910
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1911
        }
1912
    }
1913

    
1914
    /**
1915
     * Handle "getrevsionanddoctype" action Given a docid, return it's current
1916
     * revision and doctype from data base The output is String look like
1917
     * "rev;doctype"
1918
     */
1919
    private void handleGetRevisionAndDocTypeAction(PrintWriter out,
1920
            Hashtable params)
1921
    {
1922
        // To store doc parameter
1923
        String[] docs = new String[10];
1924
        // Store a single doc id
1925
        String givenDocId = null;
1926
        // Get docid from parameters
1927
        if (params.containsKey("docid")) {
1928
            docs = (String[]) params.get("docid");
1929
        }
1930
        // Get first docid form string array
1931
        givenDocId = docs[0];
1932

    
1933
        try {
1934
            // Make sure there is a docid
1935
            if (givenDocId == null || givenDocId.equals("")) { throw new Exception(
1936
                    "User didn't specify docid!"); }//if
1937

    
1938
            // Create a DBUtil object
1939
            DBUtil dbutil = new DBUtil();
1940
            // Get a rev and doctype
1941
            String revAndDocType = dbutil
1942
                    .getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
1943
            out.println(revAndDocType);
1944

    
1945
        } catch (Exception e) {
1946
            // Handle exception
1947
            out.println("<?xml version=\"1.0\"?>");
1948
            out.println("<error>");
1949
            out.println(e.getMessage());
1950
            out.println("</error>");
1951
        }
1952

    
1953
    }
1954

    
1955
    /**
1956
     * Handle "getaccesscontrol" action. Read Access Control List from db
1957
     * connection in XML format
1958
     */
1959
    private void handleGetAccessControlAction(PrintWriter out,
1960
            Hashtable params, HttpServletResponse response, String username,
1961
            String[] groupnames)
1962
    {
1963
        DBConnection dbConn = null;
1964
        int serialNumber = -1;
1965
        String docid = ((String[]) params.get("docid"))[0];
1966

    
1967
        try {
1968

    
1969
            // get connection from the pool
1970
            dbConn = DBConnectionPool
1971
                    .getDBConnection("MetaCatServlet.handleGetAccessControlAction");
1972
            serialNumber = dbConn.getCheckOutSerialNumber();
1973
            AccessControlList aclobj = new AccessControlList(dbConn);
1974
            String acltext = aclobj.getACL(docid, username, groupnames);
1975
            out.println(acltext);
1976

    
1977
        } catch (Exception e) {
1978
            out.println("<?xml version=\"1.0\"?>");
1979
            out.println("<error>");
1980
            out.println(e.getMessage());
1981
            out.println("</error>");
1982
        } finally {
1983
            // Retrun db connection to pool
1984
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1985
        }
1986
    }
1987

    
1988
    /**
1989
     * Handle the "getprincipals" action. Read all principals from
1990
     * authentication scheme in XML format
1991
     */
1992
    private void handleGetPrincipalsAction(PrintWriter out, String user,
1993
            String password)
1994
    {
1995
        try {
1996
            AuthSession auth = new AuthSession();
1997
            String principals = auth.getPrincipals(user, password);
1998
            out.println(principals);
1999

    
2000
        } catch (Exception e) {
2001
            out.println("<?xml version=\"1.0\"?>");
2002
            out.println("<error>");
2003
            out.println(e.getMessage());
2004
            out.println("</error>");
2005
        }
2006
    }
2007

    
2008
    /**
2009
     * Handle "getdoctypes" action. Read all doctypes from db connection in XML
2010
     * format
2011
     */
2012
    private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
2013
            HttpServletResponse response)
2014
    {
2015
        try {
2016
            DBUtil dbutil = new DBUtil();
2017
            String doctypes = dbutil.readDoctypes();
2018
            out.println(doctypes);
2019
        } catch (Exception e) {
2020
            out.println("<?xml version=\"1.0\"?>");
2021
            out.println("<error>");
2022
            out.println(e.getMessage());
2023
            out.println("</error>");
2024
        }
2025
    }
2026

    
2027
    /**
2028
     * Handle the "getdtdschema" action. Read DTD or Schema file for a given
2029
     * doctype from Metacat catalog system
2030
     */
2031
    private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
2032
            HttpServletResponse response)
2033
    {
2034

    
2035
        String doctype = null;
2036
        String[] doctypeArr = (String[]) params.get("doctype");
2037

    
2038
        // get only the first doctype specified in the list of doctypes
2039
        // it could be done for all doctypes in that list
2040
        if (doctypeArr != null) {
2041
            doctype = ((String[]) params.get("doctype"))[0];
2042
        }
2043

    
2044
        try {
2045
            DBUtil dbutil = new DBUtil();
2046
            String dtdschema = dbutil.readDTDSchema(doctype);
2047
            out.println(dtdschema);
2048

    
2049
        } catch (Exception e) {
2050
            out.println("<?xml version=\"1.0\"?>");
2051
            out.println("<error>");
2052
            out.println(e.getMessage());
2053
            out.println("</error>");
2054
        }
2055

    
2056
    }
2057

    
2058
    /**
2059
     * Handle the "getlastdocid" action. Get the latest docid with rev number
2060
     * from db connection in XML format
2061
     */
2062
    private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
2063
            HttpServletResponse response)
2064
    {
2065

    
2066
        String scope = ((String[]) params.get("scope"))[0];
2067
        if (scope == null) {
2068
            scope = ((String[]) params.get("username"))[0];
2069
        }
2070

    
2071
        try {
2072

    
2073
            DBUtil dbutil = new DBUtil();
2074
            String lastDocid = dbutil.getMaxDocid(scope);
2075
            out.println("<?xml version=\"1.0\"?>");
2076
            out.println("<lastDocid>");
2077
            out.println("  <scope>" + scope + "</scope>");
2078
            out.println("  <docid>" + lastDocid + "</docid>");
2079
            out.println("</lastDocid>");
2080

    
2081
        } catch (Exception e) {
2082
            out.println("<?xml version=\"1.0\"?>");
2083
            out.println("<error>");
2084
            out.println(e.getMessage());
2085
            out.println("</error>");
2086
        }
2087
    }
2088

    
2089
    /**
2090
     * Print a report from the event log based on filter parameters passed in
2091
     * from the web.
2092
     *
2093
     * TODO: make sure urlencoding of timestamp params is working
2094
     *
2095
     * @param params the parameters from the web request
2096
     * @param request the http request object for getting request details
2097
     * @param response the http response object for writing output
2098
     */
2099
    private void handleGetLogAction(Hashtable params, HttpServletRequest request,
2100
            HttpServletResponse response)
2101
    {
2102
        // Get all of the parameters in the correct formats
2103
        String[] ipAddress = (String[])params.get("ipaddress");
2104
        String[] principal = (String[])params.get("principal");
2105
        String[] docid = (String[])params.get("docid");
2106
        String[] event = (String[])params.get("event");
2107
        String[] startArray = (String[]) params.get("start");
2108
        String[] endArray = (String[]) params.get("end");
2109
        String start = null;
2110
        String end = null;
2111
        if (startArray != null) {
2112
            start = startArray[0];
2113
        }
2114
        if (endArray != null) {
2115
            end = endArray[0];
2116
        }
2117
        Timestamp startDate = null;
2118
        Timestamp endDate = null;
2119
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
2120
        try {
2121
            if (start != null) {
2122
                startDate = new Timestamp((format.parse(start)).getTime());
2123
            }
2124
            if (end != null) {
2125
                endDate = new Timestamp((format.parse(end)).getTime());
2126
            }
2127
        } catch (ParseException e) {
2128
            System.out.println("Failed to created Timestamp from input.");
2129
        }
2130

    
2131
        // Request the report by passing the filter parameters
2132
        try {
2133
            response.setContentType("text/xml");
2134
            PrintWriter out = response.getWriter();
2135
            out.println(EventLog.getInstance().getReport(ipAddress, principal,
2136
                    docid, event, startDate, endDate));
2137
            out.close();
2138
        } catch (IOException e) {
2139
            MetaCatUtil.debugMessage(
2140
                    "Could not open http response for writing: "
2141
                    + e.getMessage(), 5);
2142
        }
2143
    }
2144

    
2145
    /**
2146
     * Handle documents passed to metacat that are encoded using the
2147
     * "multipart/form-data" mime type. This is typically used for uploading
2148
     * data files which may be binary and large.
2149
     */
2150
    private void handleMultipartForm(HttpServletRequest request,
2151
            HttpServletResponse response)
2152
    {
2153
        PrintWriter out = null;
2154
        String action = null;
2155

    
2156
        // Parse the multipart form, and save the parameters in a Hashtable and
2157
        // save the FileParts in a hashtable
2158

    
2159
        Hashtable params = new Hashtable();
2160
        Hashtable fileList = new Hashtable();
2161
        int sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit")))
2162
                .intValue();
2163
        MetaCatUtil.debugMessage(
2164
                "The limit size of data file is: " + sizeLimit, 50);
2165

    
2166
        try {
2167
            // MBJ: need to put filesize limit in Metacat config
2168
            // (metacat.properties)
2169
            MultipartParser mp = new MultipartParser(request,
2170
                    sizeLimit * 1024 * 1024);
2171
            Part part;
2172
            while ((part = mp.readNextPart()) != null) {
2173
                String name = part.getName();
2174

    
2175
                if (part.isParam()) {
2176
                    // it's a parameter part
2177
                    ParamPart paramPart = (ParamPart) part;
2178
                    String value = paramPart.getStringValue();
2179
                    params.put(name, value);
2180
                    if (name.equals("action")) {
2181
                        action = value;
2182
                    }
2183
                } else if (part.isFile()) {
2184
                    // it's a file part
2185
                    FilePart filePart = (FilePart) part;
2186
                    fileList.put(name, filePart);
2187

    
2188
                    // Stop once the first file part is found, otherwise going
2189
                    // onto the
2190
                    // next part prevents access to the file contents. So...for
2191
                    // upload
2192
                    // to work, the datafile must be the last part
2193
                    break;
2194
                }
2195
            }
2196
        } catch (IOException ioe) {
2197
            try {
2198
                out = response.getWriter();
2199
            } catch (IOException ioe2) {
2200
                System.err
2201
                        .println("Fatal Error: couldn't get response output stream.");
2202
            }
2203
            out.println("<?xml version=\"1.0\"?>");
2204
            out.println("<error>");
2205
            out.println("Error: problem reading multipart data.");
2206
            out.println("</error>");
2207
        }
2208

    
2209
        // Get the session information
2210
        String username = null;
2211
        String password = null;
2212
        String[] groupnames = null;
2213
        String sess_id = null;
2214

    
2215
        // be aware of session expiration on every request
2216
        HttpSession sess = request.getSession(true);
2217
        if (sess.isNew()) {
2218
            // session expired or has not been stored b/w user requests
2219
            username = "public";
2220
            sess.setAttribute("username", username);
2221
        } else {
2222
            username = (String) sess.getAttribute("username");
2223
            password = (String) sess.getAttribute("password");
2224
            groupnames = (String[]) sess.getAttribute("groupnames");
2225
            try {
2226
                sess_id = (String) sess.getId();
2227
            } catch (IllegalStateException ise) {
2228
                System.out
2229
                        .println("error in  handleMultipartForm: this shouldn't "
2230
                                + "happen: the session should be valid: "
2231
                                + ise.getMessage());
2232
            }
2233
        }
2234

    
2235
        // Get the out stream
2236
        try {
2237
            out = response.getWriter();
2238
        } catch (IOException ioe2) {
2239
            MetaCatUtil.debugMessage("Fatal Error: couldn't get response "
2240
                    + "output stream.", 30);
2241
        }
2242

    
2243
        if (action.equals("upload")) {
2244
            if (username != null && !username.equals("public")) {
2245
                handleUploadAction(request, out, params, fileList, username,
2246
                        groupnames);
2247
            } else {
2248

    
2249
                out.println("<?xml version=\"1.0\"?>");
2250
                out.println("<error>");
2251
                out.println("Permission denied for " + action);
2252
                out.println("</error>");
2253
            }
2254
        } else {
2255
            /*
2256
             * try { out = response.getWriter(); } catch (IOException ioe2) {
2257
             * System.err.println("Fatal Error: couldn't get response output
2258
             * stream.");
2259
             */
2260
            out.println("<?xml version=\"1.0\"?>");
2261
            out.println("<error>");
2262
            out.println(
2263
                    "Error: action not registered.  Please report this error.");
2264
            out.println("</error>");
2265
        }
2266
        out.close();
2267
    }
2268

    
2269
    /**
2270
     * Handle the upload action by saving the attached file to disk and
2271
     * registering it in the Metacat db
2272
     */
2273
    private void handleUploadAction(HttpServletRequest request,
2274
            PrintWriter out, Hashtable params, Hashtable fileList,
2275
            String username, String[] groupnames)
2276
    {
2277
        //PrintWriter out = null;
2278
        //Connection conn = null;
2279
        String action = null;
2280
        String docid = null;
2281

    
2282
        /*
2283
         * response.setContentType("text/xml"); try { out =
2284
         * response.getWriter(); } catch (IOException ioe2) {
2285
         * System.err.println("Fatal Error: couldn't get response output
2286
         * stream.");
2287
         */
2288

    
2289
        if (params.containsKey("docid")) {
2290
            docid = (String) params.get("docid");
2291
        }
2292

    
2293
        // Make sure we have a docid and datafile
2294
        if (docid != null && fileList.containsKey("datafile")) {
2295

    
2296
            // Get a reference to the file part of the form
2297
            FilePart filePart = (FilePart) fileList.get("datafile");
2298
            String fileName = filePart.getFileName();
2299
            MetaCatUtil.debugMessage("Uploading filename: " + fileName, 10);
2300

    
2301
            // Check if the right file existed in the uploaded data
2302
            if (fileName != null) {
2303

    
2304
                try {
2305
                    //MetaCatUtil.debugMessage("Upload datafile " + docid
2306
                    // +"...", 10);
2307
                    //If document get lock data file grant
2308
                    if (DocumentImpl.getDataFileLockGrant(docid)) {
2309
                        // register the file in the database (which generates
2310
                        // an exception
2311
                        //if the docid is not acceptable or other untoward
2312
                        // things happen
2313
                        DocumentImpl.registerDocument(fileName, "BIN", docid,
2314
                                username, groupnames);
2315

    
2316
                        // Save the data file to disk using "docid" as the name
2317
                        dataDirectory.mkdirs();
2318
                        File newFile = new File(dataDirectory, docid);
2319
                        long size = filePart.writeTo(newFile);
2320

    
2321
                        EventLog.getInstance().log(request.getRemoteAddr(),
2322
                                username, docid, "upload");
2323
                        // Force replication this data file
2324
                        // To data file, "insert" and update is same
2325
                        // The fourth parameter is null. Because it is
2326
                        // notification server
2327
                        // and this method is in MetaCatServerlet. It is
2328
                        // original command,
2329
                        // not get force replication info from another metacat
2330
                        ForceReplicationHandler frh = new ForceReplicationHandler(
2331
                                docid, "insert", false, null);
2332

    
2333
                        // set content type and other response header fields
2334
                        // first
2335
                        out.println("<?xml version=\"1.0\"?>");
2336
                        out.println("<success>");
2337
                        out.println("<docid>" + docid + "</docid>");
2338
                        out.println("<size>" + size + "</size>");
2339
                        out.println("</success>");
2340
                    }
2341

    
2342
                } catch (Exception e) {
2343
                    out.println("<?xml version=\"1.0\"?>");
2344
                    out.println("<error>");
2345
                    out.println(e.getMessage());
2346
                    out.println("</error>");
2347
                }
2348
            } else {
2349
                // the field did not contain a file
2350
                out.println("<?xml version=\"1.0\"?>");
2351
                out.println("<error>");
2352
                out.println("The uploaded data did not contain a valid file.");
2353
                out.println("</error>");
2354
            }
2355
        } else {
2356
            // Error bcse docid missing or file missing
2357
            out.println("<?xml version=\"1.0\"?>");
2358
            out.println("<error>");
2359
            out.println("The uploaded data did not contain a valid docid "
2360
                    + "or valid file.");
2361
            out.println("</error>");
2362
        }
2363
    }
2364

    
2365
    /*
2366
     * A method to handle set access action
2367
     */
2368
    private void handleSetAccessAction(PrintWriter out, Hashtable params,
2369
            String username)
2370
    {
2371
        String[] docList = null;
2372
        String[] principalList = null;
2373
        String[] permissionList = null;
2374
        String[] permTypeList = null;
2375
        String[] permOrderList = null;
2376
        String permission = null;
2377
        String permType = null;
2378
        String permOrder = null;
2379
        Vector errorList = new Vector();
2380
        String error = null;
2381
        Vector successList = new Vector();
2382
        String success = null;
2383

    
2384
        // Get parameters
2385
        if (params.containsKey("docid")) {
2386
            docList = (String[]) params.get("docid");
2387
        }
2388
        if (params.containsKey("principal")) {
2389
            principalList = (String[]) params.get("principal");
2390
        }
2391
        if (params.containsKey("permission")) {
2392
            permissionList = (String[]) params.get("permission");
2393

    
2394
        }
2395
        if (params.containsKey("permType")) {
2396
            permTypeList = (String[]) params.get("permType");
2397

    
2398
        }
2399
        if (params.containsKey("permOrder")) {
2400
            permOrderList = (String[]) params.get("permOrder");
2401

    
2402
        }
2403

    
2404
        // Make sure the parameter is not null
2405
        if (docList == null || principalList == null || permTypeList == null
2406
                || permissionList == null) {
2407
            error = "Please check your parameter list, it should look like: "
2408
                    + "?action=setaccess&docid=pipeline.1.1&principal=public"
2409
                    + "&permission=read&permType=allow&permOrder=allowFirst";
2410
            errorList.addElement(error);
2411
            outputResponse(successList, errorList, out);
2412
            return;
2413
        }
2414

    
2415
        // Only select first element for permission, type and order
2416
        permission = permissionList[0];
2417
        permType = permTypeList[0];
2418
        if (permOrderList != null) {
2419
            permOrder = permOrderList[0];
2420
        }
2421

    
2422
        // Get package doctype set
2423
        Vector packageSet = MetaCatUtil.getOptionList(MetaCatUtil
2424
                .getOption("packagedoctypeset"));
2425
        //debug
2426
        if (packageSet != null) {
2427
            for (int i = 0; i < packageSet.size(); i++) {
2428
                MetaCatUtil.debugMessage("doctype in package set: "
2429
                        + (String) packageSet.elementAt(i), 34);
2430
            }
2431
        }
2432

    
2433
        // handle every accessionNumber
2434
        for (int i = 0; i < docList.length; i++) {
2435
            String accessionNumber = docList[i];
2436
            String owner = null;
2437
            String publicId = null;
2438
            // Get document owner and public id
2439
            try {
2440
                owner = getFieldValueForDoc(accessionNumber, "user_owner");
2441
                publicId = getFieldValueForDoc(accessionNumber, "doctype");
2442
            } catch (Exception e) {
2443
                MetaCatUtil.debugMessage("Error in handleSetAccessAction: "
2444
                        + e.getMessage(), 30);
2445
                error = "Error in set access control for document - "
2446
                        + accessionNumber + e.getMessage();
2447
                errorList.addElement(error);
2448
                continue;
2449
            }
2450
            //check if user is the owner. Only owner can do owner
2451
            if (username == null || owner == null || !username.equals(owner)) {
2452
                error = "User - " + username
2453
                        + " does not have permission to set "
2454
                        + "access control for docid - " + accessionNumber;
2455
                errorList.addElement(error);
2456
                continue;
2457
            }
2458

    
2459
            // If docid publicid is BIN data file or other beta4, 6 package
2460
            // document
2461
            // we could not do set access control. Because we don't want
2462
            // inconsistent
2463
            // to its access docuemnt
2464
            if (publicId != null && packageSet != null
2465
                    && packageSet.contains(publicId)) {
2466
                error = "Could not set access control to document "
2467
                        + accessionNumber
2468
                        + "because it is in a pakcage and it has a access file for it";
2469
                errorList.addElement(error);
2470
                continue;
2471
            }
2472

    
2473
            // for every principle
2474
            for (int j = 0; j < principalList.length; j++) {
2475
                String principal = principalList[j];
2476
                try {
2477
                    //insert permission
2478
                    AccessControlForSingleFile accessControl = new AccessControlForSingleFile(
2479
                            accessionNumber, principal, permission, permType,
2480
                            permOrder);
2481
                    accessControl.insertPermissions();
2482
                    success = "Set access control to document "
2483
                            + accessionNumber + " successfully";
2484
                    successList.addElement(success);
2485
                } catch (Exception ee) {
2486
                    MetaCatUtil.debugMessage(
2487
                            "Erorr in handleSetAccessAction2: "
2488
                                    + ee.getMessage(), 30);
2489
                    error = "Faild to set access control for document "
2490
                            + accessionNumber + " because " + ee.getMessage();
2491
                    errorList.addElement(error);
2492
                    continue;
2493
                }
2494
            }
2495
        }
2496
        outputResponse(successList, errorList, out);
2497
    }
2498

    
2499
    /*
2500
     * A method try to determin a docid's public id, if couldn't find null will
2501
     * be returned.
2502
     */
2503
    private String getFieldValueForDoc(String accessionNumber, String fieldName)
2504
            throws Exception
2505
    {
2506
        if (accessionNumber == null || accessionNumber.equals("")
2507
                || fieldName == null || fieldName.equals("")) { throw new Exception(
2508
                "Docid or field name was not specified"); }
2509

    
2510
        PreparedStatement pstmt = null;
2511
        ResultSet rs = null;
2512
        String fieldValue = null;
2513
        String docId = null;
2514
        DBConnection conn = null;
2515
        int serialNumber = -1;
2516

    
2517
        // get rid of revision if access number has
2518
        docId = MetaCatUtil.getDocIdFromString(accessionNumber);
2519
        try {
2520
            //check out DBConnection
2521
            conn = DBConnectionPool
2522
                    .getDBConnection("MetaCatServlet.getPublicIdForDoc");
2523
            serialNumber = conn.getCheckOutSerialNumber();
2524
            pstmt = conn.prepareStatement("SELECT " + fieldName
2525
                    + " FROM xml_documents " + "WHERE docid = ? ");
2526

    
2527
            pstmt.setString(1, docId);
2528
            pstmt.execute();
2529
            rs = pstmt.getResultSet();
2530
            boolean hasRow = rs.next();
2531
            int perm = 0;
2532
            if (hasRow) {
2533
                fieldValue = rs.getString(1);
2534
            } else {
2535
                throw new Exception("Could not find document: "
2536
                        + accessionNumber);
2537
            }
2538
        } catch (Exception e) {
2539
            MetaCatUtil.debugMessage(
2540
                    "Exception in MetacatServlet.getPublicIdForDoc: "
2541
                            + e.getMessage(), 30);
2542
            throw e;
2543
        } finally {
2544
            try {
2545
                rs.close();
2546
                pstmt.close();
2547

    
2548
            } finally {
2549
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2550
            }
2551
        }
2552
        return fieldValue;
2553
    }
2554

    
2555
    /*
2556
     * A method to output setAccess action result
2557
     */
2558
    private void outputResponse(Vector successList, Vector errorList,
2559
            PrintWriter out)
2560
    {
2561
        boolean error = false;
2562
        boolean success = false;
2563
        // Output prolog
2564
        out.println(PROLOG);
2565
        // output success message
2566
        if (successList != null) {
2567
            for (int i = 0; i < successList.size(); i++) {
2568
                out.println(SUCCESS);
2569
                out.println((String) successList.elementAt(i));
2570
                out.println(SUCCESSCLOSE);
2571
                success = true;
2572
            }
2573
        }
2574
        // output error message
2575
        if (errorList != null) {
2576
            for (int i = 0; i < errorList.size(); i++) {
2577
                out.println(ERROR);
2578
                out.println((String) errorList.elementAt(i));
2579
                out.println(ERRORCLOSE);
2580
                error = true;
2581
            }
2582
        }
2583

    
2584
        // if no error and no success info, send a error that nothing happened
2585
        if (!error && !success) {
2586
            out.println(ERROR);
2587
            out.println("Nothing happend for setaccess action");
2588
            out.println(ERRORCLOSE);
2589
        }
2590
    }
2591
}
(42-42/63)