Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements a metadata catalog as a java Servlet
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Matt Jones, Dan Higgins, Jivka Bojilova, Chad Berkley
7
 *    Release: @release@
8
 *
9
 *   '$Author: jones $'
10
 *     '$Date: 2004-04-02 13:43:51 -0800 (Fri, 02 Apr 2004) $'
11
 * '$Revision: 2102 $'
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.util.Enumeration;
42
import java.util.Hashtable;
43
import java.util.PropertyResourceBundle;
44
import java.util.Vector;
45
import java.util.zip.ZipEntry;
46
import java.util.zip.ZipOutputStream;
47

    
48
import javax.servlet.ServletConfig;
49
import javax.servlet.ServletContext;
50
import javax.servlet.ServletException;
51
import javax.servlet.ServletOutputStream;
52
import javax.servlet.http.HttpServlet;
53
import javax.servlet.http.HttpServletRequest;
54
import javax.servlet.http.HttpServletResponse;
55
import javax.servlet.http.HttpSession;
56

    
57
import edu.ucsb.nceas.utilities.Options;
58

    
59
import org.ecoinformatics.eml.EMLParser;
60

    
61
import com.oreilly.servlet.multipart.FilePart;
62
import com.oreilly.servlet.multipart.MultipartParser;
63
import com.oreilly.servlet.multipart.ParamPart;
64
import com.oreilly.servlet.multipart.Part;
65

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

    
106
    private ServletConfig config = null;
107

    
108
    private ServletContext context = null;
109

    
110
    private String resultStyleURL = null;
111

    
112
    private String xmlcatalogfile = null;
113

    
114
    private String saxparser = null;
115

    
116
    private String datafilepath = null;
117

    
118
    private File dataDirectory = null;
119

    
120
    private String servletpath = null;
121

    
122
    private String htmlpath = null;
123

    
124
    private PropertyResourceBundle options = null;
125

    
126
    private MetaCatUtil util = null;
127

    
128
    private DBConnectionPool connPool = null;
129

    
130
    private Hashtable sessionHash = new Hashtable();
131

    
132
    private static final String PROLOG = "<?xml version=\"1.0\"?>";
133

    
134
    private static final String SUCCESS = "<success>";
135

    
136
    private static final String SUCCESSCLOSE = "</success>";
137

    
138
    private static final String ERROR = "<error>";
139

    
140
    private static final String ERRORCLOSE = "</error>";
141

    
142
    public static final String SCHEMALOCATIONKEYWORD = ":schemaLocation";
143

    
144
    public static final String NONAMESPACELOCATION = ":noNamespaceSchemaLocation";
145

    
146
    public static final String EML2KEYWORD = ":eml";
147

    
148
    public static final String XMLFORMAT = "xml";
149

    
150
    private static final String CONFIG_DIR = "WEB-INF";
151

    
152
    private static final String CONFIG_NAME = "metacat.properties";
153

    
154
    /**
155
     * Initialize the servlet by creating appropriate database connections
156
     */
157
    public void init(ServletConfig config) throws ServletException
158
    {
159
        try {
160
            super.init(config);
161
            this.config = config;
162
            this.context = config.getServletContext();
163

    
164
            // Initialize the properties file for our options
165
            String dirPath = context.getRealPath(CONFIG_DIR);
166
            File propertyFile = new File(dirPath, CONFIG_NAME);
167
            Options options = null;
168
            try {
169
                options = Options.initialize(propertyFile);
170
                MetaCatUtil.debugMessage("Options configured: "
171
                        + options.getOption("configured"), 20);
172
            } catch (IOException ioe) {
173
                MetaCatUtil.debugMessage("Error in loading options: "
174
                        + ioe.getMessage(), 20);
175
            }
176

    
177
            util = new MetaCatUtil();
178

    
179
            //initial DBConnection pool
180
            connPool = DBConnectionPool.getInstance();
181

    
182
            // Get the configuration file information
183
            resultStyleURL = MetaCatUtil.getOption("resultStyleURL");
184
            xmlcatalogfile = MetaCatUtil.getOption("xmlcatalogfile");
185
            saxparser = MetaCatUtil.getOption("saxparser");
186
            datafilepath = MetaCatUtil.getOption("datafilepath");
187
            dataDirectory = new File(datafilepath);
188
            servletpath = MetaCatUtil.getOption("servletpath");
189
            htmlpath = MetaCatUtil.getOption("htmlpath");
190

    
191
            System.out.println("Metacat (" + Version.getVersion()
192
                    + ") initialized.");
193
        } catch (ServletException ex) {
194
            throw ex;
195
        } catch (SQLException e) {
196
            MetaCatUtil.debugMessage("Error in MetacatServlet.init: "
197
                    + e.getMessage(), 20);
198
        }
199
    }
200

    
201
    /**
202
     * Close all db connections from the pool
203
     */
204
    public void destroy()
205
    {
206
        // Close all db connection
207
        System.out.println("Destroying MetacatServlet");
208
        connPool.release();
209
    }
210

    
211
    /** Handle "GET" method requests from HTTP clients */
212
    public void doGet(HttpServletRequest request, HttpServletResponse response)
213
            throws ServletException, IOException
214
    {
215

    
216
        // Process the data and send back the response
217
        handleGetOrPost(request, response);
218
    }
219

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

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

    
229
    /**
230
     * Control servlet response depending on the action parameter specified
231
     */
232
    private void handleGetOrPost(HttpServletRequest request,
233
            HttpServletResponse response) throws ServletException, IOException
234
    {
235

    
236
        if (util == null) {
237
            util = new MetaCatUtil();
238
        }
239
        /*
240
         * MetaCatUtil.debugMessage("Connection pool size: "
241
         * +connPool.getSizeOfDBConnectionPool(),10);
242
         * MetaCatUtil.debugMessage("Free DBConnection number: "
243
         */
244
        //If all DBConnection in the pool are free and DBConnection pool
245
        //size is greater than initial value, shrink the connection pool
246
        //size to initial value
247
        DBConnectionPool.shrinkDBConnectionPoolSize();
248

    
249
        //Debug message to print out the method which have a busy DBConnection
250
        connPool.printMethodNameHavingBusyDBConnection();
251

    
252
        String ctype = request.getContentType();
253
        if (ctype != null && ctype.startsWith("multipart/form-data")) {
254
            handleMultipartForm(request, response);
255
        } else {
256

    
257
            String name = null;
258
            String[] value = null;
259
            String[] docid = new String[3];
260
            Hashtable params = new Hashtable();
261
            Enumeration paramlist = request.getParameterNames();
262

    
263
            while (paramlist.hasMoreElements()) {
264

    
265
                name = (String) paramlist.nextElement();
266
                value = request.getParameterValues(name);
267

    
268
                // Decode the docid and mouse click information
269
                if (name.endsWith(".y")) {
270
                    docid[0] = name.substring(0, name.length() - 2);
271
                    params.put("docid", docid);
272
                    name = "ypos";
273
                }
274
                if (name.endsWith(".x")) {
275
                    name = "xpos";
276
                }
277

    
278
                params.put(name, value);
279
            }
280

    
281
            //handle param is emptpy
282
            if (params.isEmpty() || params == null) { return; }
283

    
284
            //if the user clicked on the input images, decode which image
285
            //was clicked then set the action.
286
            String action = ((String[]) params.get("action"))[0];
287
            MetaCatUtil.debugMessage("Line 230: Action is: " + action, 1);
288

    
289
            // This block handles session management for the servlet
290
            // by looking up the current session information for all actions
291
            // other than "login" and "logout"
292
            String username = null;
293
            String password = null;
294
            String[] groupnames = null;
295
            String sess_id = null;
296

    
297
            // handle login action
298
            if (action.equals("login")) {
299
                PrintWriter out = response.getWriter();
300
                handleLoginAction(out, params, request, response);
301
                out.close();
302

    
303
                // handle logout action
304
            } else if (action.equals("logout")) {
305
                PrintWriter out = response.getWriter();
306
                handleLogoutAction(out, params, request, response);
307
                out.close();
308

    
309
                // handle shrink DBConnection request
310
            } else if (action.equals("shrink")) {
311
                PrintWriter out = response.getWriter();
312
                boolean success = false;
313
                //If all DBConnection in the pool are free and DBConnection
314
                // pool
315
                //size is greater than initial value, shrink the connection
316
                // pool
317
                //size to initial value
318
                success = DBConnectionPool.shrinkConnectionPoolSize();
319
                if (success) {
320
                    //if successfully shrink the pool size to initial value
321
                    out.println("DBConnection Pool shrunk successfully.");
322
                }//if
323
                else {
324
                    out.println("DBConnection pool not shrunk successfully.");
325
                }
326
                //close out put
327
                out.close();
328

    
329
                // aware of session expiration on every request
330
            } else {
331
                HttpSession sess = request.getSession(true);
332
                if (sess.isNew() && !params.containsKey("sessionid")) {
333
                    // session expired or has not been stored b/w user requests
334
                    MetaCatUtil.debugMessage(
335
                            "in session is new or no sessionid", 40);
336
                    username = "public";
337
                    sess.setAttribute("username", username);
338
                } else {
339
                    MetaCatUtil.debugMessage("in session is not new or "
340
                            + " has sessionid parameter", 40);
341
                    try {
342
                        if (params.containsKey("sessionid")) {
343
                            sess_id = ((String[]) params.get("sessionid"))[0];
344
                            MetaCatUtil.debugMessage("in has sessionid "
345
                                    + sess_id, 40);
346
                            if (sessionHash.containsKey(sess_id)) {
347
                                MetaCatUtil.debugMessage("find the id "
348
                                        + sess_id + " in hash table", 40);
349
                                sess = (HttpSession) sessionHash.get(sess_id);
350
                            }
351
                        } else {
352
                            // we already store the session in login, so we
353
                            // don't need here
354
                            /*
355
                             * MetaCatUtil.debugMessage("in no sessionid
356
                             * parameter ", 40); sess_id =
357
                             * (String)sess.getId();
358
                             * MetaCatUtil.debugMessage("storing the session id "
359
                             * + sess_id + " which has username " +
360
                             * sess.getAttribute("username") + " into session
361
                             * hash in handleGetOrPost method", 35);
362
                             */
363
                        }
364
                    } catch (IllegalStateException ise) {
365
                        System.out.println(
366
                                "error in handleGetOrPost: this shouldn't "
367
                                + "happen: the session should be valid: "
368
                                + ise.getMessage());
369
                    }
370

    
371
                    username = (String) sess.getAttribute("username");
372
                    MetaCatUtil.debugMessage("The user name from session is: "
373
                            + username, 20);
374
                    password = (String) sess.getAttribute("password");
375
                    groupnames = (String[]) sess.getAttribute("groupnames");
376
                }
377

    
378
                //make user user username should be public
379
                if (username == null || (username.trim().equals(""))) {
380
                    username = "public";
381
                }
382
                MetaCatUtil.debugMessage("The user is : " + username, 5);
383
            }
384
            // Now that we know the session is valid, we can delegate the
385
            // request
386
            // to a particular action handler
387
            if (action.equals("query")) {
388
                PrintWriter out = response.getWriter();
389
                handleQuery(out, params, response, username, groupnames,
390
                        sess_id);
391
                out.close();
392
            } else if (action.equals("squery")) {
393
                PrintWriter out = response.getWriter();
394
                if (params.containsKey("query")) {
395
                    handleSQuery(out, params, response, username, groupnames,
396
                            sess_id);
397
                    out.close();
398
                } else {
399
                    out.println(
400
                            "Illegal action squery without \"query\" parameter");
401
                    out.close();
402
                }
403
            } else if (action.equals("export")) {
404

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

    
526
            //util.closeConnections();
527
            // Close the stream to the client
528
            //out.close();
529
        }
530
    }
531

    
532
    // LOGIN & LOGOUT SECTION
533
    /**
534
     * Handle the login request. Create a new session object. Do user
535
     * authentication through the session.
536
     */
537
    private void handleLoginAction(PrintWriter out, Hashtable params,
538
            HttpServletRequest request, HttpServletResponse response)
539
    {
540

    
541
        AuthSession sess = null;
542
        String un = ((String[]) params.get("username"))[0];
543
        MetaCatUtil.debugMessage("user " + un + " try to login", 20);
544
        String pw = ((String[]) params.get("password"))[0];
545
        String action = ((String[]) params.get("action"))[0];
546
        String qformat = ((String[]) params.get("qformat"))[0];
547

    
548
        try {
549
            sess = new AuthSession();
550
        } catch (Exception e) {
551
            System.out.println("error in MetacatServlet.handleLoginAction: "
552
                    + e.getMessage());
553
            out.println(e.getMessage());
554
            return;
555
        }
556
        boolean isValid = sess.authenticate(request, un, pw);
557

    
558
        //if it is authernticate is true, store the session
559
        if (isValid) {
560
            HttpSession session = sess.getSessions();
561
            String id = session.getId();
562
            MetaCatUtil.debugMessage("Store session id " + id
563
                    + "which has username" + session.getAttribute("username")
564
                    + " into hash in login method", 35);
565
            sessionHash.put(id, session);
566
        }
567

    
568
        // format and transform the output
569
        if (qformat.equals("xml")) {
570
            response.setContentType("text/xml");
571
            out.println(sess.getMessage());
572
        } else {
573
            try {
574
                DBTransform trans = new DBTransform();
575
                response.setContentType("text/html");
576
                trans.transformXMLDocument(sess.getMessage(),
577
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
578
                        out, null);
579
            } catch (Exception e) {
580

    
581
                MetaCatUtil.debugMessage(
582
                        "Error in MetaCatServlet.handleLoginAction: "
583
                                + e.getMessage(), 30);
584
            }
585
        }
586
    }
587

    
588
    /**
589
     * Handle the logout request. Close the connection.
590
     */
591
    private void handleLogoutAction(PrintWriter out, Hashtable params,
592
            HttpServletRequest request, HttpServletResponse response)
593
    {
594

    
595
        String qformat = ((String[]) params.get("qformat"))[0];
596

    
597
        // close the connection
598
        HttpSession sess = request.getSession(false);
599
        MetaCatUtil.debugMessage("After get session in logout request", 40);
600
        if (sess != null) {
601
            MetaCatUtil.debugMessage("The session id " + sess.getId()
602
                    + " will be invalidate in logout action", 30);
603
            MetaCatUtil.debugMessage("The session contains user "
604
                    + sess.getAttribute("username")
605
                    + " will be invalidate in logout action", 30);
606
            sess.invalidate();
607
        }
608

    
609
        // produce output
610
        StringBuffer output = new StringBuffer();
611
        output.append("<?xml version=\"1.0\"?>");
612
        output.append("<logout>");
613
        output.append("User logged out");
614
        output.append("</logout>");
615

    
616
        //format and transform the output
617
        if (qformat.equals("xml")) {
618
            response.setContentType("text/xml");
619
            out.println(output.toString());
620
        } else {
621
            try {
622
                DBTransform trans = new DBTransform();
623
                response.setContentType("text/html");
624
                trans.transformXMLDocument(output.toString(),
625
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
626
                        out, null);
627
            } catch (Exception e) {
628
                MetaCatUtil.debugMessage(
629
                        "Error in MetaCatServlet.handleLogoutAction"
630
                                + e.getMessage(), 30);
631
            }
632
        }
633
    }
634

    
635
    // END OF LOGIN & LOGOUT SECTION
636

    
637
    // SQUERY & QUERY SECTION
638
    /**
639
     * Retreive the squery xml, execute it and display it
640
     * 
641
     * @param out the output stream to the client
642
     * @param params the Hashtable of parameters that should be included in the
643
     *            squery.
644
     * @param response the response object linked to the client
645
     * @param conn the database connection
646
     */
647
    protected void handleSQuery(PrintWriter out, Hashtable params,
648
            HttpServletResponse response, String user, String[] groups,
649
            String sessionid)
650
    {
651
        double startTime = System.currentTimeMillis() / 1000;
652
        DBQuery queryobj = new DBQuery(saxparser);
653
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
654
        double outPutTime = System.currentTimeMillis() / 1000;
655
        MetaCatUtil.debugMessage("total search time: "
656
                + (outPutTime - startTime), 30);
657

    
658
    }
659

    
660
    /**
661
     * Create the xml query, execute it and display the results.
662
     * 
663
     * @param out the output stream to the client
664
     * @param params the Hashtable of parameters that should be included in the
665
     *            squery.
666
     * @param response the response object linked to the client
667
     */
668
    protected void handleQuery(PrintWriter out, Hashtable params,
669
            HttpServletResponse response, String user, String[] groups,
670
            String sessionid)
671
    {
672
        //create the query and run it
673
        String xmlquery = DBQuery.createSQuery(params);
674
        String[] queryArray = new String[1];
675
        queryArray[0] = xmlquery;
676
        params.put("query", queryArray);
677
        double startTime = System.currentTimeMillis() / 1000;
678
        DBQuery queryobj = new DBQuery(saxparser);
679
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
680
        double outPutTime = System.currentTimeMillis() / 1000;
681
        MetaCatUtil.debugMessage("total search time: "
682
                + (outPutTime - startTime), 30);
683

    
684
        //handleSQuery(out, params, response,user, groups, sessionid);
685
    }
686

    
687
    // END OF SQUERY & QUERY SECTION
688

    
689
    //Exoport section
690
    /**
691
     * Handle the "export" request of data package from Metacat in zip format
692
     * 
693
     * @param params the Hashtable of HTTP request parameters
694
     * @param response the HTTP response object linked to the client
695
     * @param user the username sent the request
696
     * @param groups the user's groupnames
697
     */
698
    private void handleExportAction(Hashtable params, 
699
            HttpServletResponse response, 
700
            String user, String[] groups, String passWord)
701
    {
702
        // Output stream
703
        ServletOutputStream out = null;
704
        // Zip output stream
705
        ZipOutputStream zOut = null;
706
        DocumentImpl docImpls = null;
707
        DBQuery queryObj = null;
708

    
709
        String[] docs = new String[10];
710
        String docId = "";
711

    
712
        try {
713
            // read the params
714
            if (params.containsKey("docid")) {
715
                docs = (String[]) params.get("docid");
716
            }
717
            // Create a DBuery to handle export
718
            queryObj = new DBQuery(saxparser);
719
            // Get the docid
720
            docId = docs[0];
721
            // Make sure the client specify docid
722
            if (docId == null || docId.equals("")) {
723
                response.setContentType("text/xml"); //MIME type
724
                // Get a printwriter
725
                PrintWriter pw = response.getWriter();
726
                // Send back message
727
                pw.println("<?xml version=\"1.0\"?>");
728
                pw.println("<error>");
729
                pw.println("You didn't specify requested docid");
730
                pw.println("</error>");
731
                // Close printwriter
732
                pw.close();
733
                return;
734
            }
735
            // Get output stream
736
            out = response.getOutputStream();
737
            response.setContentType("application/zip"); //MIME type
738
            zOut = new ZipOutputStream(out);
739
            zOut = queryObj
740
                    .getZippedPackage(docId, out, user, groups, passWord);
741
            zOut.finish(); //terminate the zip file
742
            zOut.close(); //close the zip stream
743

    
744
        } catch (Exception e) {
745
            try {
746
                response.setContentType("text/xml"); //MIME type
747
                // Send error message back
748
                if (out != null) {
749
                    PrintWriter pw = new PrintWriter(out);
750
                    pw.println("<?xml version=\"1.0\"?>");
751
                    pw.println("<error>");
752
                    pw.println(e.getMessage());
753
                    pw.println("</error>");
754
                    // Close printwriter
755
                    pw.close();
756
                    // Close output stream
757
                    out.close();
758
                }
759
                // Close zip output stream
760
                if (zOut != null) {
761
                    zOut.close();
762
                }
763
            } catch (IOException ioe) {
764
                MetaCatUtil.debugMessage("Problem with the servlet output "
765
                        + "in MetacatServlet.handleExportAction: "
766
                        + ioe.getMessage(), 30);
767
            }
768

    
769
            MetaCatUtil.debugMessage(
770
                    "Error in MetacatServlet.handleExportAction: "
771
                            + e.getMessage(), 30);
772
            e.printStackTrace(System.out);
773

    
774
        }
775

    
776
    }
777

    
778
    /**
779
     * In eml2 document, the xml can have inline data and data was stripped off
780
     * and store in file system. This action can be used to read inline data
781
     * only
782
     * 
783
     * @param params the Hashtable of HTTP request parameters
784
     * @param response the HTTP response object linked to the client
785
     * @param user the username sent the request
786
     * @param groups the user's groupnames
787
     */
788
    private void handleReadInlineDataAction(Hashtable params,
789
            HttpServletRequest request, HttpServletResponse response, 
790
            String user, String passWord, String[] groups)
791
    {
792
        String[] docs = new String[10];
793
        String inlineDataId = null;
794
        String docId = "";
795
        ServletOutputStream out = null;
796

    
797
        try {
798
            // read the params
799
            if (params.containsKey("inlinedataid")) {
800
                docs = (String[]) params.get("inlinedataid");
801
            }
802
            // Get the docid
803
            inlineDataId = docs[0];
804
            // Make sure the client specify docid
805
            if (inlineDataId == null || inlineDataId.equals("")) { 
806
                throw new Exception("You didn't specify requested inlinedataid"); }
807

    
808
            // check for permission
809
            docId = MetaCatUtil
810
                    .getDocIdWithoutRevFromInlineDataID(inlineDataId);
811
            PermissionController controller = new PermissionController(docId);
812
            // check top level read permission
813
            if (!controller.hasPermission(user, groups,
814
                    AccessControlInterface.READSTRING)) {
815
                throw new Exception("User " + user
816
                        + " doesn't have permission " + " to read document "
817
                        + docId);
818
            } else if (controller.hasSubTreeAccessControl()) {
819
                // if the document has subtree control, we need to check 
820
                // subtree control
821
                // get node id for inlinedata
822
                long nodeId = getInlineDataNodeId(inlineDataId, docId);
823
                if (!controller.hasPermissionForSubTreeNode(user, groups,
824
                    AccessControlInterface.READSTRING, nodeId)) { 
825
                    throw new Exception(
826
                    "User " + user + " doesn't have permission "
827
                    + " to read inlinedata " + inlineDataId); 
828
                }
829
            }
830

    
831
            // Get output stream
832
            out = response.getOutputStream();
833
            // read the inline data from the file
834
            String inlinePath = MetaCatUtil.getOption("inlinedatafilepath");
835
            File lineData = new File(inlinePath, inlineDataId);
836
            FileInputStream input = new FileInputStream(lineData);
837
            byte[] buffer = new byte[4 * 1024];
838
            int bytes = input.read(buffer);
839
            while (bytes != -1) {
840
                out.write(buffer, 0, bytes);
841
                bytes = input.read(buffer);
842
            }
843
            out.close();
844

    
845
            EventLog.getInstance().log(request.getRemoteAddr(), user, 
846
                    inlineDataId, "readinlinedata");
847
        } catch (Exception e) {
848
            try {
849
                PrintWriter pw = null;
850
                // Send error message back
851
                if (out != null) {
852
                    pw = new PrintWriter(out);
853
                } else {
854
                    pw = response.getWriter();
855
                }
856
                pw.println("<?xml version=\"1.0\"?>");
857
                pw.println("<error>");
858
                pw.println(e.getMessage());
859
                pw.println("</error>");
860
                // Close printwriter
861
                pw.close();
862
                // Close output stream if out is not null
863
                if (out != null) {
864
                    out.close();
865
                }
866
            } catch (IOException ioe) {
867
                MetaCatUtil.debugMessage("Problem with the servlet output "
868
                        + "in MetacatServlet.handleExportAction: "
869
                        + ioe.getMessage(), 30);
870
            }
871
            MetaCatUtil.debugMessage(
872
                    "Error in MetacatServlet.handleReadInlineDataAction: "
873
                            + e.getMessage(), 30);
874
        }
875
    }
876

    
877
    /*
878
     * Get the nodeid from xml_nodes for the inlinedataid
879
     */
880
    private long getInlineDataNodeId(String inLineDataId, String docId)
881
            throws SQLException
882
    {
883
        long nodeId = 0;
884
        String INLINE = "inline";
885
        boolean hasRow;
886
        PreparedStatement pStmt = null;
887
        DBConnection conn = null;
888
        int serialNumber = -1;
889
        String sql = "SELECT nodeid FROM xml_nodes WHERE docid=? AND nodedata=? "
890
                + "AND nodetype='TEXT' AND parentnodeid IN "
891
                + "(SELECT nodeid FROM xml_nodes WHERE docid=? AND "
892
                + "nodetype='ELEMENT' AND nodename='" + INLINE + "')";
893

    
894
        try {
895
            //check out DBConnection
896
            conn = DBConnectionPool
897
                    .getDBConnection("AccessControlList.isAllowFirst");
898
            serialNumber = conn.getCheckOutSerialNumber();
899

    
900
            pStmt = conn.prepareStatement(sql);
901
            //bind value
902
            pStmt.setString(1, docId);//docid
903
            pStmt.setString(2, inLineDataId);//inlinedataid
904
            pStmt.setString(3, docId);
905
            // excute query
906
            pStmt.execute();
907
            ResultSet rs = pStmt.getResultSet();
908
            hasRow = rs.next();
909
            // get result
910
            if (hasRow) {
911
                nodeId = rs.getLong(1);
912
            }//if
913

    
914
        } catch (SQLException e) {
915
            throw e;
916
        } finally {
917
            try {
918
                pStmt.close();
919
            } finally {
920
                DBConnectionPool.returnDBConnection(conn, serialNumber);
921
            }
922
        }
923
        MetaCatUtil.debugMessage("The nodeid for inlinedataid " + inLineDataId
924
                + " is: " + nodeId, 35);
925
        return nodeId;
926
    }
927

    
928
    /**
929
     * Handle the "read" request of metadata/data files from Metacat or any
930
     * files from Internet; transformed metadata XML document into HTML
931
     * presentation if requested; zip files when more than one were requested.
932
     * 
933
     * @param params the Hashtable of HTTP request parameters
934
     * @param request the HTTP request object linked to the client
935
     * @param response the HTTP response object linked to the client
936
     * @param user the username sent the request
937
     * @param groups the user's groupnames
938
     */
939
    private void handleReadAction(Hashtable params, HttpServletRequest request,
940
            HttpServletResponse response, String user, String passWord,
941
            String[] groups)
942
    {
943
        ServletOutputStream out = null;
944
        ZipOutputStream zout = null;
945
        PrintWriter pw = null;
946
        boolean zip = false;
947
        boolean withInlineData = true;
948

    
949
        try {
950
            String[] docs = new String[0];
951
            String docid = "";
952
            String qformat = "";
953
            String abstrpath = null;
954

    
955
            // read the params
956
            if (params.containsKey("docid")) {
957
                docs = (String[]) params.get("docid");
958
            }
959
            if (params.containsKey("qformat")) {
960
                qformat = ((String[]) params.get("qformat"))[0];
961
            }
962
            // the param for only metadata (eml)
963
            if (params.containsKey("inlinedata")) {
964

    
965
                String inlineData = ((String[]) params.get("inlinedata"))[0];
966
                if (inlineData.equalsIgnoreCase("false")) {
967
                    withInlineData = false;
968
                }
969
            }
970
            if ((docs.length > 1) || qformat.equals("zip")) {
971
                zip = true;
972
                out = response.getOutputStream();
973
                response.setContentType("application/zip"); //MIME type
974
                zout = new ZipOutputStream(out);
975
            }
976
            // go through the list of docs to read
977
            for (int i = 0; i < docs.length; i++) {
978
                try {
979

    
980
                    URL murl = new URL(docs[i]);
981
                    Hashtable murlQueryStr = MetaCatUtil.parseQuery(
982
                            murl.getQuery());
983
                    // case docid="http://.../?docid=aaa"
984
                    // or docid="metacat://.../?docid=bbb"
985
                    if (murlQueryStr.containsKey("docid")) {
986
                        // get only docid, eliminate the rest
987
                        docid = (String) murlQueryStr.get("docid");
988
                        if (zip) {
989
                            addDocToZip(request, docid, zout, user, groups);
990
                        } else {
991
                            readFromMetacat(request, response, docid, qformat,
992
                                    abstrpath, user, groups, zip, zout,
993
                                    withInlineData, params);
994
                        }
995

    
996
                        // case docid="http://.../filename"
997
                    } else {
998
                        docid = docs[i];
999
                        if (zip) {
1000
                            addDocToZip(request, docid, zout, user, groups);
1001
                        } else {
1002
                            readFromURLConnection(response, docid);
1003
                        }
1004
                    }
1005
                    
1006
                } catch (MalformedURLException mue) {
1007
                    docid = docs[i];
1008
                    if (zip) {
1009
                        addDocToZip(request, docid, zout, user, groups);
1010
                    } else {
1011
                        readFromMetacat(request, response, docid, qformat, 
1012
                                abstrpath, user, groups, zip, zout, 
1013
                                withInlineData, params);
1014
                    }
1015
                }
1016
            }
1017

    
1018
            if (zip) {
1019
                zout.finish(); //terminate the zip file
1020
                zout.close(); //close the zip stream
1021
            }
1022

    
1023
        } catch (McdbDocNotFoundException notFoundE) {
1024
            // To handle doc not found exception
1025
            // the docid which didn't be found
1026
            String notFoundDocId = notFoundE.getUnfoundDocId();
1027
            String notFoundRevision = notFoundE.getUnfoundRevision();
1028
            MetaCatUtil.debugMessage("Missed id: " + notFoundDocId, 30);
1029
            MetaCatUtil.debugMessage("Missed rev: " + notFoundRevision, 30);
1030
            try {
1031
                // read docid from remote server
1032
                readFromRemoteMetaCat(response, notFoundDocId,
1033
                        notFoundRevision, user, passWord, out, zip, zout);
1034
                // Close zout outputstream
1035
                if (zout != null) {
1036
                    zout.close();
1037
                }
1038
                // close output stream
1039
                if (out != null) {
1040
                    out.close();
1041
                }
1042

    
1043
            } catch (Exception exc) {
1044
                MetaCatUtil.debugMessage(
1045
                        "Erorr in MetacatServlet.hanldReadAction: "
1046
                                + exc.getMessage(), 30);
1047
                try {
1048
                    if (out != null) {
1049
                        response.setContentType("text/xml");
1050
                        // Send back error message by printWriter
1051
                        pw = new PrintWriter(out);
1052
                        pw.println("<?xml version=\"1.0\"?>");
1053
                        pw.println("<error>");
1054
                        pw.println(notFoundE.getMessage());
1055
                        pw.println("</error>");
1056
                        pw.close();
1057
                        out.close();
1058

    
1059
                    } else {
1060
                        response.setContentType("text/xml"); //MIME type
1061
                        // Send back error message if out = null
1062
                        if (pw == null) {
1063
                            // If pw is null, open the respnose
1064
                            pw = response.getWriter();
1065
                        }
1066
                        pw.println("<?xml version=\"1.0\"?>");
1067
                        pw.println("<error>");
1068
                        pw.println(notFoundE.getMessage());
1069
                        pw.println("</error>");
1070
                        pw.close();
1071
                    }
1072
                    // close zout
1073
                    if (zout != null) {
1074
                        zout.close();
1075
                    }
1076
                } catch (IOException ie) {
1077
                    MetaCatUtil.debugMessage("Problem with the servlet output "
1078
                            + "in MetacatServlet.handleReadAction: "
1079
                            + ie.getMessage(), 30);
1080
                }
1081
            }
1082
        } catch (Exception e) {
1083
            try {
1084

    
1085
                if (out != null) {
1086
                    response.setContentType("text/xml"); //MIME type
1087
                    pw = new PrintWriter(out);
1088
                    pw.println("<?xml version=\"1.0\"?>");
1089
                    pw.println("<error>");
1090
                    pw.println(e.getMessage());
1091
                    pw.println("</error>");
1092
                    pw.close();
1093
                    out.close();
1094
                } else {
1095
                    response.setContentType("text/xml"); //MIME type
1096
                    // Send back error message if out = null
1097
                    if (pw == null) {
1098
                        pw = response.getWriter();
1099
                    }
1100
                    pw.println("<?xml version=\"1.0\"?>");
1101
                    pw.println("<error>");
1102
                    pw.println(e.getMessage());
1103
                    pw.println("</error>");
1104
                    pw.close();
1105

    
1106
                }
1107
                // Close zip output stream
1108
                if (zout != null) {
1109
                    zout.close();
1110
                }
1111

    
1112
            } catch (IOException ioe) {
1113
                MetaCatUtil.debugMessage("Problem with the servlet output "
1114
                        + "in MetacatServlet.handleReadAction: "
1115
                        + ioe.getMessage(), 30);
1116
                ioe.printStackTrace(System.out);
1117

    
1118
            }
1119

    
1120
            MetaCatUtil.debugMessage(
1121
                    "Error in MetacatServlet.handleReadAction: "
1122
                            + e.getMessage(), 30);
1123
            //e.printStackTrace(System.out);
1124
        }
1125
    }
1126

    
1127
    /** read metadata or data from Metacat 
1128
     */
1129
    private void readFromMetacat(HttpServletRequest request, 
1130
            HttpServletResponse response, String docid, String qformat,
1131
            String abstrpath, String user, String[] groups, boolean zip,
1132
            ZipOutputStream zout, boolean withInlineData, Hashtable params)
1133
            throws ClassNotFoundException, IOException, SQLException,
1134
            McdbException, Exception
1135
    {
1136

    
1137
        try {
1138

    
1139
            DocumentImpl doc = new DocumentImpl(docid);
1140

    
1141
            //check the permission for read
1142
            if (!doc.hasReadPermission(user, groups, docid)) {
1143
                Exception e = new Exception("User " + user
1144
                        + " does not have permission"
1145
                        + " to read the document with the docid " + docid);
1146

    
1147
                throw e;
1148
            }
1149

    
1150
            if (doc.getRootNodeID() == 0) {
1151
                // this is data file
1152
                String filepath = MetaCatUtil.getOption("datafilepath");
1153
                if (!filepath.endsWith("/")) {
1154
                    filepath += "/";
1155
                }
1156
                String filename = filepath + docid;
1157
                FileInputStream fin = null;
1158
                fin = new FileInputStream(filename);
1159

    
1160
                //MIME type
1161
                String contentType = getServletContext().getMimeType(filename);
1162
                if (contentType == null) {
1163
                    ContentTypeProvider provider = new ContentTypeProvider(
1164
                            docid);
1165
                    contentType = provider.getContentType();
1166
                    MetaCatUtil.debugMessage("Final contenttype is: "
1167
                            + contentType, 30);
1168
                }
1169

    
1170
                response.setContentType(contentType);
1171
                // if we decide to use "application/octet-stream" for all data
1172
                // returns
1173
                // response.setContentType("application/octet-stream");
1174

    
1175
                try {
1176

    
1177
                    ServletOutputStream out = response.getOutputStream();
1178
                    byte[] buf = new byte[4 * 1024]; // 4K buffer
1179
                    int b = fin.read(buf);
1180
                    while (b != -1) {
1181
                        out.write(buf, 0, b);
1182
                        b = fin.read(buf);
1183
                    }
1184
                } finally {
1185
                    if (fin != null) fin.close();
1186
                }
1187
                
1188
            } else {
1189
                // this is metadata doc
1190
                if (qformat.equals("xml")) {
1191

    
1192
                    // set content type first
1193
                    response.setContentType("text/xml"); //MIME type
1194
                    PrintWriter out = response.getWriter();
1195
                    doc.toXml(out, user, groups, withInlineData);
1196
                } else {
1197
                    response.setContentType("text/html"); //MIME type
1198
                    PrintWriter out = response.getWriter();
1199

    
1200
                    // Look up the document type
1201
                    String doctype = doc.getDoctype();
1202
                    // Transform the document to the new doctype
1203
                    DBTransform dbt = new DBTransform();
1204
                    dbt.transformXMLDocument(doc.toString(user, groups,
1205
                            withInlineData), doctype, "-//W3C//HTML//EN",
1206
                            qformat, out, params);
1207
                }
1208

    
1209
            }
1210
            EventLog.getInstance().log(request.getRemoteAddr(), user, 
1211
                    docid, "read");
1212
        } catch (Exception except) {
1213
            throw except;
1214
        }
1215
    }
1216

    
1217
    /** 
1218
     * read data from URLConnection 
1219
     */
1220
    private void readFromURLConnection(HttpServletResponse response,
1221
            String docid) throws IOException, MalformedURLException
1222
    {
1223
        ServletOutputStream out = response.getOutputStream();
1224
        String contentType = getServletContext().getMimeType(docid); //MIME
1225
                                                                     // type
1226
        if (contentType == null) {
1227
            if (docid.endsWith(".xml")) {
1228
                contentType = "text/xml";
1229
            } else if (docid.endsWith(".css")) {
1230
                contentType = "text/css";
1231
            } else if (docid.endsWith(".dtd")) {
1232
                contentType = "text/plain";
1233
            } else if (docid.endsWith(".xsd")) {
1234
                contentType = "text/xml";
1235
            } else if (docid.endsWith("/")) {
1236
                contentType = "text/html";
1237
            } else {
1238
                File f = new File(docid);
1239
                if (f.isDirectory()) {
1240
                    contentType = "text/html";
1241
                } else {
1242
                    contentType = "application/octet-stream";
1243
                }
1244
            }
1245
        }
1246
        response.setContentType(contentType);
1247
        // if we decide to use "application/octet-stream" for all data returns
1248
        // response.setContentType("application/octet-stream");
1249

    
1250
        // this is http url
1251
        URL url = new URL(docid);
1252
        BufferedInputStream bis = null;
1253
        try {
1254
            bis = new BufferedInputStream(url.openStream());
1255
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1256
            int b = bis.read(buf);
1257
            while (b != -1) {
1258
                out.write(buf, 0, b);
1259
                b = bis.read(buf);
1260
            }
1261
        } finally {
1262
            if (bis != null) bis.close();
1263
        }
1264

    
1265
    }
1266

    
1267
    /** 
1268
     * read file/doc and write to ZipOutputStream
1269
     * 
1270
     * @param docid
1271
     * @param zout
1272
     * @param user
1273
     * @param groups
1274
     * @throws ClassNotFoundException
1275
     * @throws IOException
1276
     * @throws SQLException
1277
     * @throws McdbException
1278
     * @throws Exception
1279
     */
1280
    private void addDocToZip(HttpServletRequest request, String docid, 
1281
            ZipOutputStream zout, String user, String[] groups) throws
1282
            ClassNotFoundException, IOException, SQLException, McdbException,
1283
            Exception
1284
    {
1285
        byte[] bytestring = null;
1286
        ZipEntry zentry = null;
1287

    
1288
        try {
1289
            URL url = new URL(docid);
1290

    
1291
            // this http url; read from URLConnection; add to zip
1292
            zentry = new ZipEntry(docid);
1293
            zout.putNextEntry(zentry);
1294
            BufferedInputStream bis = null;
1295
            try {
1296
                bis = new BufferedInputStream(url.openStream());
1297
                byte[] buf = new byte[4 * 1024]; // 4K buffer
1298
                int b = bis.read(buf);
1299
                while (b != -1) {
1300
                    zout.write(buf, 0, b);
1301
                    b = bis.read(buf);
1302
                }
1303
            } finally {
1304
                if (bis != null) bis.close();
1305
            }
1306
            zout.closeEntry();
1307

    
1308
        } catch (MalformedURLException mue) {
1309

    
1310
            // this is metacat doc (data file or metadata doc)
1311
            try {
1312
                DocumentImpl doc = new DocumentImpl(docid);
1313

    
1314
                //check the permission for read
1315
                if (!doc.hasReadPermission(user, groups, docid)) {
1316
                    Exception e = new Exception("User " + user
1317
                            + " does not have "
1318
                            + "permission to read the document with the docid "
1319
                            + docid);
1320
                    throw e;
1321
                }
1322

    
1323
                if (doc.getRootNodeID() == 0) {
1324
                    // this is data file; add file to zip
1325
                    String filepath = MetaCatUtil.getOption("datafilepath");
1326
                    if (!filepath.endsWith("/")) {
1327
                        filepath += "/";
1328
                    }
1329
                    String filename = filepath + docid;
1330
                    FileInputStream fin = null;
1331
                    fin = new FileInputStream(filename);
1332
                    try {
1333

    
1334
                        zentry = new ZipEntry(docid);
1335
                        zout.putNextEntry(zentry);
1336
                        byte[] buf = new byte[4 * 1024]; // 4K buffer
1337
                        int b = fin.read(buf);
1338
                        while (b != -1) {
1339
                            zout.write(buf, 0, b);
1340
                            b = fin.read(buf);
1341
                        }
1342
                    } finally {
1343
                        if (fin != null) fin.close();
1344
                    }
1345
                    zout.closeEntry();
1346

    
1347
                } else {
1348
                    // this is metadata doc; add doc to zip
1349
                    bytestring = doc.toString().getBytes();
1350
                    zentry = new ZipEntry(docid + ".xml");
1351
                    zentry.setSize(bytestring.length);
1352
                    zout.putNextEntry(zentry);
1353
                    zout.write(bytestring, 0, bytestring.length);
1354
                    zout.closeEntry();
1355
                }
1356
                EventLog.getInstance().log(request.getRemoteAddr(), user, 
1357
                        docid, "read");
1358
            } catch (Exception except) {
1359
                throw except;
1360
            }
1361
        }
1362
    }
1363

    
1364
    /**
1365
     * If metacat couldn't find a data file or document locally, it will read
1366
     * this docid from its home server. This is for the replication feature
1367
     */
1368
    private void readFromRemoteMetaCat(HttpServletResponse response,
1369
            String docid, String rev, String user, String password,
1370
            ServletOutputStream out, boolean zip, ZipOutputStream zout)
1371
            throws Exception
1372
    {
1373
        // Create a object of RemoteDocument, "" is for zipEntryPath
1374
        RemoteDocument remoteDoc = new RemoteDocument(docid, rev, user,
1375
                password, "");
1376
        String docType = remoteDoc.getDocType();
1377
        // Only read data file
1378
        if (docType.equals("BIN")) {
1379
            // If it is zip format
1380
            if (zip) {
1381
                remoteDoc.readDocumentFromRemoteServerByZip(zout);
1382
            } else {
1383
                if (out == null) {
1384
                    out = response.getOutputStream();
1385
                }
1386
                response.setContentType("application/octet-stream");
1387
                remoteDoc.readDocumentFromRemoteServer(out);
1388
            }
1389
        } else {
1390
            throw new Exception("Docid: " + docid + "." + rev
1391
                    + " couldn't find");
1392
        }
1393
    }
1394

    
1395
    /**
1396
     * Handle the database putdocument request and write an XML document to the
1397
     * database connection
1398
     */
1399
    private void handleInsertOrUpdateAction(HttpServletRequest request,
1400
            HttpServletResponse response, PrintWriter out, Hashtable params,
1401
            String user, String[] groups)
1402
    {
1403
        DBConnection dbConn = null;
1404
        int serialNumber = -1;
1405

    
1406
        try {
1407
            // Get the document indicated
1408
            String[] doctext = (String[]) params.get("doctext");
1409

    
1410
            String pub = null;
1411
            if (params.containsKey("public")) {
1412
                pub = ((String[]) params.get("public"))[0];
1413
            }
1414

    
1415
            StringReader dtd = null;
1416
            if (params.containsKey("dtdtext")) {
1417
                String[] dtdtext = (String[]) params.get("dtdtext");
1418
                try {
1419
                    if (!dtdtext[0].equals("")) {
1420
                        dtd = new StringReader(dtdtext[0]);
1421
                    }
1422
                } catch (NullPointerException npe) {
1423
                }
1424
            }
1425

    
1426
            StringReader xml = new StringReader(doctext[0]);
1427
            boolean validate = false;
1428
            DocumentImplWrapper documentWrapper = null;
1429
            try {
1430
                // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ...
1431
                // >
1432
                // in order to decide whether to use validation parser
1433
                validate = needDTDValidation(xml);
1434
                if (validate) {
1435
                    // set a dtd base validation parser
1436
                    String rule = DocumentImpl.DTD;
1437
                    documentWrapper = new DocumentImplWrapper(rule, validate);
1438
                } else if (needSchemaValidation(xml)) {
1439
                    // for eml2
1440
                    if (needEml2Validation(xml)) {
1441
                        // set eml2 base validation parser
1442
                        String rule = DocumentImpl.EML2;
1443
                        // using emlparser to check id validation
1444
                        EMLParser parser = new EMLParser(doctext[0]);
1445
                        documentWrapper = new DocumentImplWrapper(rule, true);
1446
                    } else {
1447
                        // set schema base validation parser
1448
                        String rule = DocumentImpl.SCHEMA;
1449
                        documentWrapper = new DocumentImplWrapper(rule, true);
1450
                    }
1451
                } else {
1452
                    documentWrapper = new DocumentImplWrapper("", false);
1453
                }
1454

    
1455
                String[] action = (String[]) params.get("action");
1456
                String[] docid = (String[]) params.get("docid");
1457
                String newdocid = null;
1458

    
1459
                String doAction = null;
1460
                if (action[0].equals("insert")) {
1461
                    doAction = "INSERT";
1462
                } else if (action[0].equals("update")) {
1463
                    doAction = "UPDATE";
1464
                }
1465

    
1466
                try {
1467
                    // get a connection from the pool
1468
                    dbConn = DBConnectionPool
1469
                            .getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1470
                    serialNumber = dbConn.getCheckOutSerialNumber();
1471

    
1472
                    // write the document to the database
1473
                    try {
1474
                        String accNumber = docid[0];
1475
                        MetaCatUtil.debugMessage("" + doAction + " "
1476
                                + accNumber + "...", 10);
1477
                        if (accNumber.equals("")) {
1478
                            accNumber = null;
1479
                        }
1480
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1481
                                doAction, accNumber, user, groups);
1482
                        EventLog.getInstance().log(request.getRemoteAddr(), 
1483
                                user, accNumber, action[0]);
1484
                    } catch (NullPointerException npe) {
1485
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1486
                                doAction, null, user, groups);
1487
                        EventLog.getInstance().log(request.getRemoteAddr(), 
1488
                                user, "", action[0]);
1489
                    }
1490
                }
1491
                finally {
1492
                    // Return db connection
1493
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1494
                }
1495

    
1496
                // set content type and other response header fields first
1497
                //response.setContentType("text/xml");
1498
                out.println("<?xml version=\"1.0\"?>");
1499
                out.println("<success>");
1500
                out.println("<docid>" + newdocid + "</docid>");
1501
                out.println("</success>");
1502

    
1503
            } catch (NullPointerException npe) {
1504
                //response.setContentType("text/xml");
1505
                out.println("<?xml version=\"1.0\"?>");
1506
                out.println("<error>");
1507
                out.println(npe.getMessage());
1508
                out.println("</error>");
1509
            }
1510
        } catch (Exception e) {
1511
            //response.setContentType("text/xml");
1512
            out.println("<?xml version=\"1.0\"?>");
1513
            out.println("<error>");
1514
            out.println(e.getMessage());
1515
            out.println("</error>");
1516
        }
1517
    }
1518

    
1519
    /**
1520
     * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > in
1521
     * order to decide whether to use validation parser
1522
     */
1523
    private static boolean needDTDValidation(StringReader xmlreader)
1524
            throws IOException
1525
    {
1526

    
1527
        StringBuffer cbuff = new StringBuffer();
1528
        java.util.Stack st = new java.util.Stack();
1529
        boolean validate = false;
1530
        int c;
1531
        int inx;
1532

    
1533
        // read from the stream until find the keywords
1534
        while ((st.empty() || st.size() < 4) && ((c = xmlreader.read()) != -1)) {
1535
            cbuff.append((char) c);
1536

    
1537
            // "<!DOCTYPE" keyword is found; put it in the stack
1538
            if ((inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1) {
1539
                cbuff = new StringBuffer();
1540
                st.push("<!DOCTYPE");
1541
            }
1542
            // "PUBLIC" keyword is found; put it in the stack
1543
            if ((inx = cbuff.toString().indexOf("PUBLIC")) != -1) {
1544
                cbuff = new StringBuffer();
1545
                st.push("PUBLIC");
1546
            }
1547
            // "SYSTEM" keyword is found; put it in the stack
1548
            if ((inx = cbuff.toString().indexOf("SYSTEM")) != -1) {
1549
                cbuff = new StringBuffer();
1550
                st.push("SYSTEM");
1551
            }
1552
            // ">" character is found; put it in the stack
1553
            // ">" is found twice: fisrt from <?xml ...?>
1554
            // and second from <!DOCTYPE ... >
1555
            if ((inx = cbuff.toString().indexOf(">")) != -1) {
1556
                cbuff = new StringBuffer();
1557
                st.push(">");
1558
            }
1559
        }
1560

    
1561
        // close the stream
1562
        xmlreader.reset();
1563

    
1564
        // check the stack whether it contains the keywords:
1565
        // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1566
        if (st.size() == 4) {
1567
            if (((String) st.pop()).equals(">")
1568
                    && (((String) st.peek()).equals("PUBLIC") | ((String) st
1569
                            .pop()).equals("SYSTEM"))
1570
                    && ((String) st.pop()).equals("<!DOCTYPE")) {
1571
                validate = true;
1572
            }
1573
        }
1574

    
1575
        MetaCatUtil.debugMessage("Validation for dtd is " + validate, 10);
1576
        return validate;
1577
    }
1578

    
1579
    // END OF INSERT/UPDATE SECTION
1580

    
1581
    /* check if the xml string contains key words to specify schema loocation */
1582
    private boolean needSchemaValidation(StringReader xml) throws IOException
1583
    {
1584
        boolean needSchemaValidate = false;
1585
        if (xml == null) {
1586
            MetaCatUtil.debugMessage("Validation for schema is "
1587
                    + needSchemaValidate, 10);
1588
            return needSchemaValidate;
1589
        }
1590
        System.out.println("before get target line");
1591
        String targetLine = getSchemaLine(xml);
1592
        System.out.println("before get target line");
1593
        // to see if the second line contain some keywords
1594
        if (targetLine != null
1595
                && (targetLine.indexOf(SCHEMALOCATIONKEYWORD) != -1 || targetLine
1596
                        .indexOf(NONAMESPACELOCATION) != -1)) {
1597
            // if contains schema location key word, should be validate
1598
            needSchemaValidate = true;
1599
        }
1600

    
1601
        MetaCatUtil.debugMessage("Validation for schema is "
1602
                + needSchemaValidate, 10);
1603
        return needSchemaValidate;
1604

    
1605
    }
1606

    
1607
    /* check if the xml string contains key words to specify schema loocation */
1608
    private boolean needEml2Validation(StringReader xml) throws IOException
1609
    {
1610
        boolean needEml2Validate = false;
1611
        String emlNameSpace = DocumentImpl.EMLNAMESPACE;
1612
        String schemaLocationContent = null;
1613
        if (xml == null) {
1614
            MetaCatUtil.debugMessage("Validation for schema is "
1615
                    + needEml2Validate, 10);
1616
            return needEml2Validate;
1617
        }
1618
        String targetLine = getSchemaLine(xml);
1619

    
1620
        if (targetLine != null) {
1621

    
1622
            int startIndex = targetLine.indexOf(SCHEMALOCATIONKEYWORD);
1623
            int start = 1;
1624
            int end = 1;
1625
            String schemaLocation = null;
1626
            int count = 0;
1627
            if (startIndex != -1) {
1628
                for (int i = startIndex; i < targetLine.length(); i++) {
1629
                    if (targetLine.charAt(i) == '"') {
1630
                        count++;
1631
                    }
1632
                    if (targetLine.charAt(i) == '"' && count == 1) {
1633
                        start = i;
1634
                    }
1635
                    if (targetLine.charAt(i) == '"' && count == 2) {
1636
                        end = i;
1637
                        break;
1638
                    }
1639
                }
1640
            }
1641
            schemaLocation = targetLine.substring(start + 1, end);
1642
            MetaCatUtil.debugMessage("schemaLocation in xml is: "
1643
                    + schemaLocation, 30);
1644
            if (schemaLocation.indexOf(emlNameSpace) != -1) {
1645
                needEml2Validate = true;
1646
            }
1647
        }
1648

    
1649
        MetaCatUtil.debugMessage("Validation for eml is " + needEml2Validate,
1650
                10);
1651
        return needEml2Validate;
1652

    
1653
    }
1654

    
1655
    private String getSchemaLine(StringReader xml) throws IOException
1656
    {
1657
        // find the line
1658
        String secondLine = null;
1659
        int count = 0;
1660
        int endIndex = 0;
1661
        int startIndex = 0;
1662
        final int TARGETNUM = 2;
1663
        StringBuffer buffer = new StringBuffer();
1664
        boolean comment = false;
1665
        char thirdPreviousCharacter = '?';
1666
        char secondPreviousCharacter = '?';
1667
        char previousCharacter = '?';
1668
        char currentCharacter = '?';
1669

    
1670
        while ((currentCharacter = (char) xml.read()) != -1) {
1671
            //in a comment
1672
            if (currentCharacter == '-' && previousCharacter == '-'
1673
                    && secondPreviousCharacter == '!'
1674
                    && thirdPreviousCharacter == '<') {
1675
                comment = true;
1676
            }
1677
            //out of comment
1678
            if (comment && currentCharacter == '>' && previousCharacter == '-'
1679
                    && secondPreviousCharacter == '-') {
1680
                comment = false;
1681
            }
1682

    
1683
            //this is not comment
1684
            if (currentCharacter != '!' && previousCharacter == '<' && !comment) {
1685
                count++;
1686
            }
1687
            // get target line
1688
            if (count == TARGETNUM && currentCharacter != '>') {
1689
                buffer.append(currentCharacter);
1690
            }
1691
            if (count == TARGETNUM && currentCharacter == '>') {
1692
                break;
1693
            }
1694
            thirdPreviousCharacter = secondPreviousCharacter;
1695
            secondPreviousCharacter = previousCharacter;
1696
            previousCharacter = currentCharacter;
1697

    
1698
        }
1699
        secondLine = buffer.toString();
1700
        MetaCatUtil
1701
                .debugMessage("the second line string is: " + secondLine, 25);
1702
        xml.reset();
1703
        return secondLine;
1704
    }
1705

    
1706
    /**
1707
     * Handle the database delete request and delete an XML document from the
1708
     * database connection
1709
     */
1710
    private void handleDeleteAction(PrintWriter out, Hashtable params,
1711
            HttpServletRequest request, HttpServletResponse response, 
1712
            String user, String[] groups)
1713
    {
1714

    
1715
        String[] docid = (String[]) params.get("docid");
1716

    
1717
        // delete the document from the database
1718
        try {
1719

    
1720
            // NOTE -- NEED TO TEST HERE
1721
            // FOR EXISTENCE OF DOCID PARAM
1722
            // BEFORE ACCESSING ARRAY
1723
            try {
1724
                DocumentImpl.delete(docid[0], user, groups);
1725
                EventLog.getInstance().log(request.getRemoteAddr(), 
1726
                    user, docid[0], "delete");
1727
                response.setContentType("text/xml");
1728
                out.println("<?xml version=\"1.0\"?>");
1729
                out.println("<success>");
1730
                out.println("Document deleted.");
1731
                out.println("</success>");
1732
            } catch (AccessionNumberException ane) {
1733
                response.setContentType("text/xml");
1734
                out.println("<?xml version=\"1.0\"?>");
1735
                out.println("<error>");
1736
                out.println("Error deleting document!!!");
1737
                out.println(ane.getMessage());
1738
                out.println("</error>");
1739
            }
1740
        } catch (Exception e) {
1741
            response.setContentType("text/xml");
1742
            out.println("<?xml version=\"1.0\"?>");
1743
            out.println("<error>");
1744
            out.println(e.getMessage());
1745
            out.println("</error>");
1746
        }
1747
    }
1748

    
1749
    /**
1750
     * Handle the validation request and return the results to the requestor
1751
     */
1752
    private void handleValidateAction(PrintWriter out, Hashtable params)
1753
    {
1754

    
1755
        // Get the document indicated
1756
        String valtext = null;
1757
        DBConnection dbConn = null;
1758
        int serialNumber = -1;
1759

    
1760
        try {
1761
            valtext = ((String[]) params.get("valtext"))[0];
1762
        } catch (Exception nullpe) {
1763

    
1764
            String docid = null;
1765
            try {
1766
                // Find the document id number
1767
                docid = ((String[]) params.get("docid"))[0];
1768

    
1769
                // Get the document indicated from the db
1770
                DocumentImpl xmldoc = new DocumentImpl(docid);
1771
                valtext = xmldoc.toString();
1772

    
1773
            } catch (NullPointerException npe) {
1774

    
1775
                out.println("<error>Error getting document ID: " + docid
1776
                        + "</error>");
1777
                //if ( conn != null ) { util.returnConnection(conn); }
1778
                return;
1779
            } catch (Exception e) {
1780

    
1781
                out.println(e.getMessage());
1782
            }
1783
        }
1784

    
1785
        try {
1786
            // get a connection from the pool
1787
            dbConn = DBConnectionPool
1788
                    .getDBConnection("MetaCatServlet.handleValidateAction");
1789
            serialNumber = dbConn.getCheckOutSerialNumber();
1790
            DBValidate valobj = new DBValidate(saxparser, dbConn);
1791
            boolean valid = valobj.validateString(valtext);
1792

    
1793
            // set content type and other response header fields first
1794

    
1795
            out.println(valobj.returnErrors());
1796

    
1797
        } catch (NullPointerException npe2) {
1798
            // set content type and other response header fields first
1799

    
1800
            out.println("<error>Error validating document.</error>");
1801
        } catch (Exception e) {
1802

    
1803
            out.println(e.getMessage());
1804
        } finally {
1805
            // Return db connection
1806
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1807
        }
1808
    }
1809

    
1810
    /**
1811
     * Handle "getrevsionanddoctype" action Given a docid, return it's current
1812
     * revision and doctype from data base The output is String look like
1813
     * "rev;doctype"
1814
     */
1815
    private void handleGetRevisionAndDocTypeAction(PrintWriter out,
1816
            Hashtable params)
1817
    {
1818
        // To store doc parameter
1819
        String[] docs = new String[10];
1820
        // Store a single doc id
1821
        String givenDocId = null;
1822
        // Get docid from parameters
1823
        if (params.containsKey("docid")) {
1824
            docs = (String[]) params.get("docid");
1825
        }
1826
        // Get first docid form string array
1827
        givenDocId = docs[0];
1828

    
1829
        try {
1830
            // Make sure there is a docid
1831
            if (givenDocId == null || givenDocId.equals("")) { throw new Exception(
1832
                    "User didn't specify docid!"); }//if
1833

    
1834
            // Create a DBUtil object
1835
            DBUtil dbutil = new DBUtil();
1836
            // Get a rev and doctype
1837
            String revAndDocType = dbutil
1838
                    .getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
1839
            out.println(revAndDocType);
1840

    
1841
        } catch (Exception e) {
1842
            // Handle exception
1843
            out.println("<?xml version=\"1.0\"?>");
1844
            out.println("<error>");
1845
            out.println(e.getMessage());
1846
            out.println("</error>");
1847
        }
1848

    
1849
    }
1850

    
1851
    /**
1852
     * Handle "getaccesscontrol" action. Read Access Control List from db
1853
     * connection in XML format
1854
     */
1855
    private void handleGetAccessControlAction(PrintWriter out,
1856
            Hashtable params, HttpServletResponse response, String username,
1857
            String[] groupnames)
1858
    {
1859
        DBConnection dbConn = null;
1860
        int serialNumber = -1;
1861
        String docid = ((String[]) params.get("docid"))[0];
1862

    
1863
        try {
1864

    
1865
            // get connection from the pool
1866
            dbConn = DBConnectionPool
1867
                    .getDBConnection("MetaCatServlet.handleGetAccessControlAction");
1868
            serialNumber = dbConn.getCheckOutSerialNumber();
1869
            AccessControlList aclobj = new AccessControlList(dbConn);
1870
            String acltext = aclobj.getACL(docid, username, groupnames);
1871
            out.println(acltext);
1872

    
1873
        } catch (Exception e) {
1874
            out.println("<?xml version=\"1.0\"?>");
1875
            out.println("<error>");
1876
            out.println(e.getMessage());
1877
            out.println("</error>");
1878
        } finally {
1879
            // Retrun db connection to pool
1880
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1881
        }
1882
    }
1883

    
1884
    /**
1885
     * Handle the "getprincipals" action. Read all principals from
1886
     * authentication scheme in XML format
1887
     */
1888
    private void handleGetPrincipalsAction(PrintWriter out, String user,
1889
            String password)
1890
    {
1891
        try {
1892
            AuthSession auth = new AuthSession();
1893
            String principals = auth.getPrincipals(user, password);
1894
            out.println(principals);
1895

    
1896
        } catch (Exception e) {
1897
            out.println("<?xml version=\"1.0\"?>");
1898
            out.println("<error>");
1899
            out.println(e.getMessage());
1900
            out.println("</error>");
1901
        }
1902
    }
1903

    
1904
    /**
1905
     * Handle "getdoctypes" action. Read all doctypes from db connection in XML
1906
     * format
1907
     */
1908
    private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
1909
            HttpServletResponse response)
1910
    {
1911
        try {
1912
            DBUtil dbutil = new DBUtil();
1913
            String doctypes = dbutil.readDoctypes();
1914
            out.println(doctypes);
1915
        } catch (Exception e) {
1916
            out.println("<?xml version=\"1.0\"?>");
1917
            out.println("<error>");
1918
            out.println(e.getMessage());
1919
            out.println("</error>");
1920
        }
1921
    }
1922

    
1923
    /**
1924
     * Handle the "getdtdschema" action. Read DTD or Schema file for a given
1925
     * doctype from Metacat catalog system
1926
     */
1927
    private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
1928
            HttpServletResponse response)
1929
    {
1930

    
1931
        String doctype = null;
1932
        String[] doctypeArr = (String[]) params.get("doctype");
1933

    
1934
        // get only the first doctype specified in the list of doctypes
1935
        // it could be done for all doctypes in that list
1936
        if (doctypeArr != null) {
1937
            doctype = ((String[]) params.get("doctype"))[0];
1938
        }
1939

    
1940
        try {
1941
            DBUtil dbutil = new DBUtil();
1942
            String dtdschema = dbutil.readDTDSchema(doctype);
1943
            out.println(dtdschema);
1944

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

    
1952
    }
1953

    
1954
    /**
1955
     * Handle the "getlastdocid" action. Get the latest docid with rev number
1956
     * from db connection in XML format
1957
     */
1958
    private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
1959
            HttpServletResponse response)
1960
    {
1961

    
1962
        String scope = ((String[]) params.get("scope"))[0];
1963
        if (scope == null) {
1964
            scope = ((String[]) params.get("username"))[0];
1965
        }
1966

    
1967
        try {
1968

    
1969
            DBUtil dbutil = new DBUtil();
1970
            String lastDocid = dbutil.getMaxDocid(scope);
1971
            out.println("<?xml version=\"1.0\"?>");
1972
            out.println("<lastDocid>");
1973
            out.println("  <scope>" + scope + "</scope>");
1974
            out.println("  <docid>" + lastDocid + "</docid>");
1975
            out.println("</lastDocid>");
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
        }
1983

    
1984
    }
1985

    
1986
    /**
1987
     * Handle documents passed to metacat that are encoded using the
1988
     * "multipart/form-data" mime type. This is typically used for uploading
1989
     * data files which may be binary and large.
1990
     */
1991
    private void handleMultipartForm(HttpServletRequest request,
1992
            HttpServletResponse response)
1993
    {
1994
        PrintWriter out = null;
1995
        String action = null;
1996

    
1997
        // Parse the multipart form, and save the parameters in a Hashtable and
1998
        // save the FileParts in a hashtable
1999

    
2000
        Hashtable params = new Hashtable();
2001
        Hashtable fileList = new Hashtable();
2002
        int sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit")))
2003
                .intValue();
2004
        MetaCatUtil.debugMessage(
2005
                "The limit size of data file is: " + sizeLimit, 50);
2006

    
2007
        try {
2008
            // MBJ: need to put filesize limit in Metacat config
2009
            // (metacat.properties)
2010
            MultipartParser mp = new MultipartParser(request,
2011
                    sizeLimit * 1024 * 1024);
2012
            Part part;
2013
            while ((part = mp.readNextPart()) != null) {
2014
                String name = part.getName();
2015

    
2016
                if (part.isParam()) {
2017
                    // it's a parameter part
2018
                    ParamPart paramPart = (ParamPart) part;
2019
                    String value = paramPart.getStringValue();
2020
                    params.put(name, value);
2021
                    if (name.equals("action")) {
2022
                        action = value;
2023
                    }
2024
                } else if (part.isFile()) {
2025
                    // it's a file part
2026
                    FilePart filePart = (FilePart) part;
2027
                    fileList.put(name, filePart);
2028

    
2029
                    // Stop once the first file part is found, otherwise going
2030
                    // onto the
2031
                    // next part prevents access to the file contents. So...for
2032
                    // upload
2033
                    // to work, the datafile must be the last part
2034
                    break;
2035
                }
2036
            }
2037
        } catch (IOException ioe) {
2038
            try {
2039
                out = response.getWriter();
2040
            } catch (IOException ioe2) {
2041
                System.err
2042
                        .println("Fatal Error: couldn't get response output stream.");
2043
            }
2044
            out.println("<?xml version=\"1.0\"?>");
2045
            out.println("<error>");
2046
            out.println("Error: problem reading multipart data.");
2047
            out.println("</error>");
2048
        }
2049

    
2050
        // Get the session information
2051
        String username = null;
2052
        String password = null;
2053
        String[] groupnames = null;
2054
        String sess_id = null;
2055

    
2056
        // be aware of session expiration on every request
2057
        HttpSession sess = request.getSession(true);
2058
        if (sess.isNew()) {
2059
            // session expired or has not been stored b/w user requests
2060
            username = "public";
2061
            sess.setAttribute("username", username);
2062
        } else {
2063
            username = (String) sess.getAttribute("username");
2064
            password = (String) sess.getAttribute("password");
2065
            groupnames = (String[]) sess.getAttribute("groupnames");
2066
            try {
2067
                sess_id = (String) sess.getId();
2068
            } catch (IllegalStateException ise) {
2069
                System.out
2070
                        .println("error in  handleMultipartForm: this shouldn't "
2071
                                + "happen: the session should be valid: "
2072
                                + ise.getMessage());
2073
            }
2074
        }
2075

    
2076
        // Get the out stream
2077
        try {
2078
            out = response.getWriter();
2079
        } catch (IOException ioe2) {
2080
            MetaCatUtil.debugMessage("Fatal Error: couldn't get response "
2081
                    + "output stream.", 30);
2082
        }
2083

    
2084
        if (action.equals("upload")) {
2085
            if (username != null && !username.equals("public")) {
2086
                handleUploadAction(request, out, params, fileList, username,
2087
                        groupnames);
2088
            } else {
2089

    
2090
                out.println("<?xml version=\"1.0\"?>");
2091
                out.println("<error>");
2092
                out.println("Permission denied for " + action);
2093
                out.println("</error>");
2094
            }
2095
        } else {
2096
            /*
2097
             * try { out = response.getWriter(); } catch (IOException ioe2) {
2098
             * System.err.println("Fatal Error: couldn't get response output
2099
             * stream.");
2100
             */
2101
            out.println("<?xml version=\"1.0\"?>");
2102
            out.println("<error>");
2103
            out.println(
2104
                    "Error: action not registered.  Please report this error.");
2105
            out.println("</error>");
2106
        }
2107
        out.close();
2108
    }
2109

    
2110
    /**
2111
     * Handle the upload action by saving the attached file to disk and
2112
     * registering it in the Metacat db
2113
     */
2114
    private void handleUploadAction(HttpServletRequest request,
2115
            PrintWriter out, Hashtable params, Hashtable fileList,
2116
            String username, String[] groupnames)
2117
    {
2118
        //PrintWriter out = null;
2119
        //Connection conn = null;
2120
        String action = null;
2121
        String docid = null;
2122

    
2123
        /*
2124
         * response.setContentType("text/xml"); try { out =
2125
         * response.getWriter(); } catch (IOException ioe2) {
2126
         * System.err.println("Fatal Error: couldn't get response output
2127
         * stream.");
2128
         */
2129

    
2130
        if (params.containsKey("docid")) {
2131
            docid = (String) params.get("docid");
2132
        }
2133

    
2134
        // Make sure we have a docid and datafile
2135
        if (docid != null && fileList.containsKey("datafile")) {
2136

    
2137
            // Get a reference to the file part of the form
2138
            FilePart filePart = (FilePart) fileList.get("datafile");
2139
            String fileName = filePart.getFileName();
2140
            MetaCatUtil.debugMessage("Uploading filename: " + fileName, 10);
2141

    
2142
            // Check if the right file existed in the uploaded data
2143
            if (fileName != null) {
2144

    
2145
                try {
2146
                    //MetaCatUtil.debugMessage("Upload datafile " + docid
2147
                    // +"...", 10);
2148
                    //If document get lock data file grant
2149
                    if (DocumentImpl.getDataFileLockGrant(docid)) {
2150
                        // register the file in the database (which generates
2151
                        // an exception
2152
                        //if the docid is not acceptable or other untoward
2153
                        // things happen
2154
                        DocumentImpl.registerDocument(fileName, "BIN", docid,
2155
                                username);
2156

    
2157
                        // Save the data file to disk using "docid" as the name
2158
                        dataDirectory.mkdirs();
2159
                        File newFile = new File(dataDirectory, docid);
2160
                        long size = filePart.writeTo(newFile);
2161

    
2162
                        EventLog.getInstance().log(request.getRemoteAddr(), 
2163
                                username, docid, "upload");
2164
                        // Force replication this data file
2165
                        // To data file, "insert" and update is same
2166
                        // The fourth parameter is null. Because it is
2167
                        // notification server
2168
                        // and this method is in MetaCatServerlet. It is
2169
                        // original command,
2170
                        // not get force replication info from another metacat
2171
                        ForceReplicationHandler frh = new ForceReplicationHandler(
2172
                                docid, "insert", false, null);
2173

    
2174
                        // set content type and other response header fields
2175
                        // first
2176
                        out.println("<?xml version=\"1.0\"?>");
2177
                        out.println("<success>");
2178
                        out.println("<docid>" + docid + "</docid>");
2179
                        out.println("<size>" + size + "</size>");
2180
                        out.println("</success>");
2181
                    }
2182

    
2183
                } catch (Exception e) {
2184
                    out.println("<?xml version=\"1.0\"?>");
2185
                    out.println("<error>");
2186
                    out.println(e.getMessage());
2187
                    out.println("</error>");
2188
                }
2189
            } else {
2190
                // the field did not contain a file
2191
                out.println("<?xml version=\"1.0\"?>");
2192
                out.println("<error>");
2193
                out.println("The uploaded data did not contain a valid file.");
2194
                out.println("</error>");
2195
            }
2196
        } else {
2197
            // Error bcse docid missing or file missing
2198
            out.println("<?xml version=\"1.0\"?>");
2199
            out.println("<error>");
2200
            out.println("The uploaded data did not contain a valid docid "
2201
                    + "or valid file.");
2202
            out.println("</error>");
2203
        }
2204
    }
2205

    
2206
    /*
2207
     * A method to handle set access action
2208
     */
2209
    private void handleSetAccessAction(PrintWriter out, Hashtable params,
2210
            String username)
2211
    {
2212
        String[] docList = null;
2213
        String[] principalList = null;
2214
        String[] permissionList = null;
2215
        String[] permTypeList = null;
2216
        String[] permOrderList = null;
2217
        String permission = null;
2218
        String permType = null;
2219
        String permOrder = null;
2220
        Vector errorList = new Vector();
2221
        String error = null;
2222
        Vector successList = new Vector();
2223
        String success = null;
2224

    
2225
        // Get parameters
2226
        if (params.containsKey("docid")) {
2227
            docList = (String[]) params.get("docid");
2228
        }
2229
        if (params.containsKey("principal")) {
2230
            principalList = (String[]) params.get("principal");
2231
        }
2232
        if (params.containsKey("permission")) {
2233
            permissionList = (String[]) params.get("permission");
2234

    
2235
        }
2236
        if (params.containsKey("permType")) {
2237
            permTypeList = (String[]) params.get("permType");
2238

    
2239
        }
2240
        if (params.containsKey("permOrder")) {
2241
            permOrderList = (String[]) params.get("permOrder");
2242

    
2243
        }
2244

    
2245
        // Make sure the parameter is not null
2246
        if (docList == null || principalList == null || permTypeList == null
2247
                || permissionList == null) {
2248
            error = "Please check your parameter list, it should look like: "
2249
                    + "?action=setaccess&docid=pipeline.1.1&principal=public"
2250
                    + "&permission=read&permType=allow&permOrder=allowFirst";
2251
            errorList.addElement(error);
2252
            outputResponse(successList, errorList, out);
2253
            return;
2254
        }
2255

    
2256
        // Only select first element for permission, type and order
2257
        permission = permissionList[0];
2258
        permType = permTypeList[0];
2259
        if (permOrderList != null) {
2260
            permOrder = permOrderList[0];
2261
        }
2262

    
2263
        // Get package doctype set
2264
        Vector packageSet = MetaCatUtil.getOptionList(MetaCatUtil
2265
                .getOption("packagedoctypeset"));
2266
        //debug
2267
        if (packageSet != null) {
2268
            for (int i = 0; i < packageSet.size(); i++) {
2269
                MetaCatUtil.debugMessage("doctype in package set: "
2270
                        + (String) packageSet.elementAt(i), 34);
2271
            }
2272
        }
2273

    
2274
        // handle every accessionNumber
2275
        for (int i = 0; i < docList.length; i++) {
2276
            String accessionNumber = docList[i];
2277
            String owner = null;
2278
            String publicId = null;
2279
            // Get document owner and public id
2280
            try {
2281
                owner = getFieldValueForDoc(accessionNumber, "user_owner");
2282
                publicId = getFieldValueForDoc(accessionNumber, "doctype");
2283
            } catch (Exception e) {
2284
                MetaCatUtil.debugMessage("Error in handleSetAccessAction: "
2285
                        + e.getMessage(), 30);
2286
                error = "Error in set access control for document - "
2287
                        + accessionNumber + e.getMessage();
2288
                errorList.addElement(error);
2289
                continue;
2290
            }
2291
            //check if user is the owner. Only owner can do owner
2292
            if (username == null || owner == null || !username.equals(owner)) {
2293
                error = "User - " + username
2294
                        + " does not have permission to set "
2295
                        + "access control for docid - " + accessionNumber;
2296
                errorList.addElement(error);
2297
                continue;
2298
            }
2299

    
2300
            // If docid publicid is BIN data file or other beta4, 6 package
2301
            // document
2302
            // we could not do set access control. Because we don't want
2303
            // inconsistent
2304
            // to its access docuemnt
2305
            if (publicId != null && packageSet != null
2306
                    && packageSet.contains(publicId)) {
2307
                error = "Could not set access control to document "
2308
                        + accessionNumber
2309
                        + "because it is in a pakcage and it has a access file for it";
2310
                errorList.addElement(error);
2311
                continue;
2312
            }
2313

    
2314
            // for every principle
2315
            for (int j = 0; j < principalList.length; j++) {
2316
                String principal = principalList[j];
2317
                try {
2318
                    //insert permission
2319
                    AccessControlForSingleFile accessControl = new AccessControlForSingleFile(
2320
                            accessionNumber, principal, permission, permType,
2321
                            permOrder);
2322
                    accessControl.insertPermissions();
2323
                    success = "Set access control to document "
2324
                            + accessionNumber + " successfully";
2325
                    successList.addElement(success);
2326
                } catch (Exception ee) {
2327
                    MetaCatUtil.debugMessage(
2328
                            "Erorr in handleSetAccessAction2: "
2329
                                    + ee.getMessage(), 30);
2330
                    error = "Faild to set access control for document "
2331
                            + accessionNumber + " because " + ee.getMessage();
2332
                    errorList.addElement(error);
2333
                    continue;
2334
                }
2335
            }
2336
        }
2337
        outputResponse(successList, errorList, out);
2338
    }
2339

    
2340
    /*
2341
     * A method try to determin a docid's public id, if couldn't find null will
2342
     * be returned.
2343
     */
2344
    private String getFieldValueForDoc(String accessionNumber, String fieldName)
2345
            throws Exception
2346
    {
2347
        if (accessionNumber == null || accessionNumber.equals("")
2348
                || fieldName == null || fieldName.equals("")) { throw new Exception(
2349
                "Docid or field name was not specified"); }
2350

    
2351
        PreparedStatement pstmt = null;
2352
        ResultSet rs = null;
2353
        String fieldValue = null;
2354
        String docId = null;
2355
        DBConnection conn = null;
2356
        int serialNumber = -1;
2357

    
2358
        // get rid of revision if access number has
2359
        docId = MetaCatUtil.getDocIdFromString(accessionNumber);
2360
        try {
2361
            //check out DBConnection
2362
            conn = DBConnectionPool
2363
                    .getDBConnection("MetaCatServlet.getPublicIdForDoc");
2364
            serialNumber = conn.getCheckOutSerialNumber();
2365
            pstmt = conn.prepareStatement("SELECT " + fieldName
2366
                    + " FROM xml_documents " + "WHERE docid = ? ");
2367

    
2368
            pstmt.setString(1, docId);
2369
            pstmt.execute();
2370
            rs = pstmt.getResultSet();
2371
            boolean hasRow = rs.next();
2372
            int perm = 0;
2373
            if (hasRow) {
2374
                fieldValue = rs.getString(1);
2375
            } else {
2376
                throw new Exception("Could not find document: "
2377
                        + accessionNumber);
2378
            }
2379
        } catch (Exception e) {
2380
            MetaCatUtil.debugMessage(
2381
                    "Exception in MetacatServlet.getPublicIdForDoc: "
2382
                            + e.getMessage(), 30);
2383
            throw e;
2384
        } finally {
2385
            try {
2386
                rs.close();
2387
                pstmt.close();
2388

    
2389
            } finally {
2390
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2391
            }
2392
        }
2393
        return fieldValue;
2394
    }
2395

    
2396
    /*
2397
     * A method to output setAccess action result
2398
     */
2399
    private void outputResponse(Vector successList, Vector errorList,
2400
            PrintWriter out)
2401
    {
2402
        boolean error = false;
2403
        boolean success = false;
2404
        // Output prolog
2405
        out.println(PROLOG);
2406
        // output success message
2407
        if (successList != null) {
2408
            for (int i = 0; i < successList.size(); i++) {
2409
                out.println(SUCCESS);
2410
                out.println((String) successList.elementAt(i));
2411
                out.println(SUCCESSCLOSE);
2412
                success = true;
2413
            }
2414
        }
2415
        // output error message
2416
        if (errorList != null) {
2417
            for (int i = 0; i < errorList.size(); i++) {
2418
                out.println(ERROR);
2419
                out.println((String) errorList.elementAt(i));
2420
                out.println(ERRORCLOSE);
2421
                error = true;
2422
            }
2423
        }
2424

    
2425
        // if no error and no success info, send a error that nothing happened
2426
        if (!error && !success) {
2427
            out.println(ERROR);
2428
            out.println("Nothing happend for setaccess action");
2429
            out.println(ERRORCLOSE);
2430
        }
2431
    }
2432
}
(41-41/61)