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 09:13:48 -0800 (Fri, 02 Apr 2004) $'
11
 * '$Revision: 2098 $'
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, groupnames,
406
                        password);
407
            } else if (action.equals("read")) {
408
                handleReadAction(params, response, username, password,
409
                        groupnames);
410
            } else if (action.equals("readinlinedata")) {
411
                handleReadInlineDataAction(params, 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(out, params, username,
417
                            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, 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 = util.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, String user, String[] groups,
700
            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
            HttpServletResponse response, String user, String passWord,
790
            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 subtree
820
                // control
821
                // get node id for inlinedata
822
                long nodeId = getInlineDataNodeId(inlineDataId, docId);
823
                if (!controller.hasPermissionForSubTreeNode(user, groups,
824
                        AccessControlInterface.READSTRING, nodeId)) { throw new Exception(
825
                        "User " + user + " doesn't have permission "
826
                                + " to read inlinedata " + inlineDataId); }//if
827

    
828
            }
829

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

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

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

    
891
        try {
892
            //check out DBConnection
893
            conn = DBConnectionPool
894
                    .getDBConnection("AccessControlList.isAllowFirst");
895
            serialNumber = conn.getCheckOutSerialNumber();
896

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

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

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

    
945
        try {
946
            String[] docs = new String[0];
947
            String docid = "";
948
            String qformat = "";
949
            String abstrpath = null;
950

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

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

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

    
991
                        // case docid="http://.../filename"
992
                    } else {
993
                        docid = docs[i];
994
                        if (zip) {
995
                            addDocToZip(docid, zout, user, groups);
996
                        } else {
997
                            readFromURLConnection(response, docid);
998
                        }
999
                    }
1000

    
1001
                    // case docid="ccc"
1002
                } catch (MalformedURLException mue) {
1003
                    docid = docs[i];
1004
                    if (zip) {
1005
                        addDocToZip(docid, zout, user, groups);
1006
                    } else {
1007
                        readFromMetacat(response, docid, qformat, abstrpath,
1008
                                user, groups, zip, zout, withInlineData, params);
1009
                    }
1010
                }
1011

    
1012
            } /* end for */
1013

    
1014
            if (zip) {
1015
                zout.finish(); //terminate the zip file
1016
                zout.close(); //close the zip stream
1017
            }
1018

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

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

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

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

    
1102
                }
1103
                // Close zip output stream
1104
                if (zout != null) {
1105
                    zout.close();
1106
                }
1107

    
1108
            } catch (IOException ioe) {
1109
                MetaCatUtil.debugMessage("Problem with the servlet output "
1110
                        + "in MetacatServlet.handleReadAction: "
1111
                        + ioe.getMessage(), 30);
1112
                ioe.printStackTrace(System.out);
1113

    
1114
            }
1115

    
1116
            MetaCatUtil.debugMessage(
1117
                    "Error in MetacatServlet.handleReadAction: "
1118
                            + e.getMessage(), 30);
1119
            //e.printStackTrace(System.out);
1120
        }
1121
    }
1122

    
1123
    /** read metadata or data from Metacat 
1124
     */
1125
    private void readFromMetacat(HttpServletResponse response, String docid,
1126
            String qformat, String abstrpath, String user, String[] groups,
1127
            boolean zip, ZipOutputStream zout, boolean withInlineData,
1128
            Hashtable params) throws ClassNotFoundException, IOException,
1129
            SQLException, McdbException, Exception
1130
    {
1131

    
1132
        try {
1133

    
1134
            DocumentImpl doc = new DocumentImpl(docid);
1135

    
1136
            //check the permission for read
1137
            if (!doc.hasReadPermission(user, groups, docid)) {
1138
                Exception e = new Exception("User " + user
1139
                        + " does not have permission"
1140
                        + " to read the document with the docid " + docid);
1141

    
1142
                throw e;
1143
            }
1144

    
1145
            if (doc.getRootNodeID() == 0) {
1146
                // this is data file
1147
                String filepath = MetaCatUtil.getOption("datafilepath");
1148
                if (!filepath.endsWith("/")) {
1149
                    filepath += "/";
1150
                }
1151
                String filename = filepath + docid;
1152
                FileInputStream fin = null;
1153
                fin = new FileInputStream(filename);
1154

    
1155
                //MIME type
1156
                String contentType = getServletContext().getMimeType(filename);
1157
                if (contentType == null) {
1158
                    ContentTypeProvider provider = new ContentTypeProvider(
1159
                            docid);
1160
                    contentType = provider.getContentType();
1161
                    MetaCatUtil.debugMessage("Final contenttype is: "
1162
                            + contentType, 30);
1163
                }
1164

    
1165
                response.setContentType(contentType);
1166
                // if we decide to use "application/octet-stream" for all data
1167
                // returns
1168
                // response.setContentType("application/octet-stream");
1169

    
1170
                try {
1171

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

    
1187
                    // set content type first
1188
                    response.setContentType("text/xml"); //MIME type
1189
                    PrintWriter out = response.getWriter();
1190
                    doc.toXml(out, user, groups, withInlineData);
1191
                } else {
1192
                    response.setContentType("text/html"); //MIME type
1193
                    PrintWriter out = response.getWriter();
1194

    
1195
                    // Look up the document type
1196
                    String doctype = doc.getDoctype();
1197
                    // Transform the document to the new doctype
1198
                    DBTransform dbt = new DBTransform();
1199
                    dbt.transformXMLDocument(doc.toString(user, groups,
1200
                            withInlineData), doctype, "-//W3C//HTML//EN",
1201
                            qformat, out, params);
1202
                }
1203

    
1204
            }
1205
        } catch (Exception except) {
1206
            throw except;
1207
        }
1208
    }
1209

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

    
1243
        // this is http url
1244
        URL url = new URL(docid);
1245
        BufferedInputStream bis = null;
1246
        try {
1247
            bis = new BufferedInputStream(url.openStream());
1248
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1249
            int b = bis.read(buf);
1250
            while (b != -1) {
1251
                out.write(buf, 0, b);
1252
                b = bis.read(buf);
1253
            }
1254
        } finally {
1255
            if (bis != null) bis.close();
1256
        }
1257

    
1258
    }
1259

    
1260
    /** 
1261
     * read file/doc and write to ZipOutputStream
1262
     * 
1263
     * @param docid
1264
     * @param zout
1265
     * @param user
1266
     * @param groups
1267
     * @throws ClassNotFoundException
1268
     * @throws IOException
1269
     * @throws SQLException
1270
     * @throws McdbException
1271
     * @throws Exception
1272
     */
1273
    private void addDocToZip(String docid, ZipOutputStream zout, String user,
1274
            String[] groups) throws ClassNotFoundException, IOException,
1275
            SQLException, McdbException, Exception
1276
    {
1277
        byte[] bytestring = null;
1278
        ZipEntry zentry = null;
1279

    
1280
        try {
1281
            URL url = new URL(docid);
1282

    
1283
            // this http url; read from URLConnection; add to zip
1284
            zentry = new ZipEntry(docid);
1285
            zout.putNextEntry(zentry);
1286
            BufferedInputStream bis = null;
1287
            try {
1288
                bis = new BufferedInputStream(url.openStream());
1289
                byte[] buf = new byte[4 * 1024]; // 4K buffer
1290
                int b = bis.read(buf);
1291
                while (b != -1) {
1292
                    zout.write(buf, 0, b);
1293
                    b = bis.read(buf);
1294
                }
1295
            } finally {
1296
                if (bis != null) bis.close();
1297
            }
1298
            zout.closeEntry();
1299

    
1300
        } catch (MalformedURLException mue) {
1301

    
1302
            // this is metacat doc (data file or metadata doc)
1303
            try {
1304
                DocumentImpl doc = new DocumentImpl(docid);
1305

    
1306
                //check the permission for read
1307
                if (!doc.hasReadPermission(user, groups, docid)) {
1308
                    Exception e = new Exception("User " + user
1309
                            + " does not have "
1310
                            + "permission to read the document with the docid "
1311
                            + docid);
1312
                    throw e;
1313
                }
1314

    
1315
                if (doc.getRootNodeID() == 0) {
1316
                    // this is data file; add file to zip
1317
                    String filepath = MetaCatUtil.getOption("datafilepath");
1318
                    if (!filepath.endsWith("/")) {
1319
                        filepath += "/";
1320
                    }
1321
                    String filename = filepath + docid;
1322
                    FileInputStream fin = null;
1323
                    fin = new FileInputStream(filename);
1324
                    try {
1325

    
1326
                        zentry = new ZipEntry(docid);
1327
                        zout.putNextEntry(zentry);
1328
                        byte[] buf = new byte[4 * 1024]; // 4K buffer
1329
                        int b = fin.read(buf);
1330
                        while (b != -1) {
1331
                            zout.write(buf, 0, b);
1332
                            b = fin.read(buf);
1333
                        }
1334
                    } finally {
1335
                        if (fin != null) fin.close();
1336
                    }
1337
                    zout.closeEntry();
1338

    
1339
                } else {
1340
                    // this is metadata doc; add doc to zip
1341
                    bytestring = doc.toString().getBytes();
1342
                    zentry = new ZipEntry(docid + ".xml");
1343
                    zentry.setSize(bytestring.length);
1344
                    zout.putNextEntry(zentry);
1345
                    zout.write(bytestring, 0, bytestring.length);
1346
                    zout.closeEntry();
1347
                }
1348
            } catch (Exception except) {
1349
                throw except;
1350
            }
1351
        }
1352
    }
1353

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

    
1385
    /**
1386
     * Handle the database putdocument request and write an XML document to the
1387
     * database connection
1388
     */
1389
    private void handleInsertOrUpdateAction(PrintWriter out, Hashtable params,
1390
            String user, String[] groups)
1391
    {
1392
        DBConnection dbConn = null;
1393
        int serialNumber = -1;
1394

    
1395
        try {
1396
            // Get the document indicated
1397
            String[] doctext = (String[]) params.get("doctext");
1398

    
1399
            String pub = null;
1400
            if (params.containsKey("public")) {
1401
                pub = ((String[]) params.get("public"))[0];
1402
            }
1403

    
1404
            StringReader dtd = null;
1405
            if (params.containsKey("dtdtext")) {
1406
                String[] dtdtext = (String[]) params.get("dtdtext");
1407
                try {
1408
                    if (!dtdtext[0].equals("")) {
1409
                        dtd = new StringReader(dtdtext[0]);
1410
                    }
1411
                } catch (NullPointerException npe) {
1412
                }
1413
            }
1414

    
1415
            StringReader xml = new StringReader(doctext[0]);
1416
            boolean validate = false;
1417
            DocumentImplWrapper documentWrapper = null;
1418
            try {
1419
                // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ...
1420
                // >
1421
                // in order to decide whether to use validation parser
1422
                validate = needDTDValidation(xml);
1423
                if (validate) {
1424
                    // set a dtd base validation parser
1425
                    String rule = DocumentImpl.DTD;
1426
                    documentWrapper = new DocumentImplWrapper(rule, validate);
1427
                } else if (needSchemaValidation(xml)) {
1428
                    // for eml2
1429
                    if (needEml2Validation(xml)) {
1430
                        // set eml2 base validation parser
1431
                        String rule = DocumentImpl.EML2;
1432
                        // using emlparser to check id validation
1433
                        EMLParser parser = new EMLParser(doctext[0]);
1434
                        documentWrapper = new DocumentImplWrapper(rule, true);
1435
                    } else {
1436
                        // set schema base validation parser
1437
                        String rule = DocumentImpl.SCHEMA;
1438
                        documentWrapper = new DocumentImplWrapper(rule, true);
1439
                    }
1440
                } else {
1441
                    documentWrapper = new DocumentImplWrapper("", false);
1442
                }
1443

    
1444
                String[] action = (String[]) params.get("action");
1445
                String[] docid = (String[]) params.get("docid");
1446
                String newdocid = null;
1447

    
1448
                String doAction = null;
1449
                if (action[0].equals("insert")) {
1450
                    doAction = "INSERT";
1451
                } else if (action[0].equals("update")) {
1452
                    doAction = "UPDATE";
1453
                }
1454

    
1455
                try {
1456
                    // get a connection from the pool
1457
                    dbConn = DBConnectionPool
1458
                            .getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1459
                    serialNumber = dbConn.getCheckOutSerialNumber();
1460

    
1461
                    // write the document to the database
1462
                    try {
1463
                        String accNumber = docid[0];
1464
                        MetaCatUtil.debugMessage("" + doAction + " "
1465
                                + accNumber + "...", 10);
1466
                        if (accNumber.equals("")) {
1467
                            accNumber = null;
1468
                        }//if
1469
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1470
                                doAction, accNumber, user, groups);
1471

    
1472
                    }//try
1473
                    catch (NullPointerException npe) {
1474
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1475
                                doAction, null, user, groups);
1476
                    }//catch
1477

    
1478
                }//try
1479
                finally {
1480
                    // Return db connection
1481
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1482
                }
1483

    
1484
                // set content type and other response header fields first
1485
                //response.setContentType("text/xml");
1486
                out.println("<?xml version=\"1.0\"?>");
1487
                out.println("<success>");
1488
                out.println("<docid>" + newdocid + "</docid>");
1489
                out.println("</success>");
1490

    
1491
            } catch (NullPointerException npe) {
1492
                //response.setContentType("text/xml");
1493
                out.println("<?xml version=\"1.0\"?>");
1494
                out.println("<error>");
1495
                out.println(npe.getMessage());
1496
                out.println("</error>");
1497
            }
1498
        } catch (Exception e) {
1499
            //response.setContentType("text/xml");
1500
            out.println("<?xml version=\"1.0\"?>");
1501
            out.println("<error>");
1502
            out.println(e.getMessage());
1503
            out.println("</error>");
1504
        }
1505
    }
1506

    
1507
    /**
1508
     * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > in
1509
     * order to decide whether to use validation parser
1510
     */
1511
    private static boolean needDTDValidation(StringReader xmlreader)
1512
            throws IOException
1513
    {
1514

    
1515
        StringBuffer cbuff = new StringBuffer();
1516
        java.util.Stack st = new java.util.Stack();
1517
        boolean validate = false;
1518
        int c;
1519
        int inx;
1520

    
1521
        // read from the stream until find the keywords
1522
        while ((st.empty() || st.size() < 4) && ((c = xmlreader.read()) != -1)) {
1523
            cbuff.append((char) c);
1524

    
1525
            // "<!DOCTYPE" keyword is found; put it in the stack
1526
            if ((inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1) {
1527
                cbuff = new StringBuffer();
1528
                st.push("<!DOCTYPE");
1529
            }
1530
            // "PUBLIC" keyword is found; put it in the stack
1531
            if ((inx = cbuff.toString().indexOf("PUBLIC")) != -1) {
1532
                cbuff = new StringBuffer();
1533
                st.push("PUBLIC");
1534
            }
1535
            // "SYSTEM" keyword is found; put it in the stack
1536
            if ((inx = cbuff.toString().indexOf("SYSTEM")) != -1) {
1537
                cbuff = new StringBuffer();
1538
                st.push("SYSTEM");
1539
            }
1540
            // ">" character is found; put it in the stack
1541
            // ">" is found twice: fisrt from <?xml ...?>
1542
            // and second from <!DOCTYPE ... >
1543
            if ((inx = cbuff.toString().indexOf(">")) != -1) {
1544
                cbuff = new StringBuffer();
1545
                st.push(">");
1546
            }
1547
        }
1548

    
1549
        // close the stream
1550
        xmlreader.reset();
1551

    
1552
        // check the stack whether it contains the keywords:
1553
        // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1554
        if (st.size() == 4) {
1555
            if (((String) st.pop()).equals(">")
1556
                    && (((String) st.peek()).equals("PUBLIC") | ((String) st
1557
                            .pop()).equals("SYSTEM"))
1558
                    && ((String) st.pop()).equals("<!DOCTYPE")) {
1559
                validate = true;
1560
            }
1561
        }
1562

    
1563
        MetaCatUtil.debugMessage("Validation for dtd is " + validate, 10);
1564
        return validate;
1565
    }
1566

    
1567
    // END OF INSERT/UPDATE SECTION
1568

    
1569
    /* check if the xml string contains key words to specify schema loocation */
1570
    private boolean needSchemaValidation(StringReader xml) throws IOException
1571
    {
1572
        boolean needSchemaValidate = false;
1573
        if (xml == null) {
1574
            MetaCatUtil.debugMessage("Validation for schema is "
1575
                    + needSchemaValidate, 10);
1576
            return needSchemaValidate;
1577
        }
1578
        System.out.println("before get target line");
1579
        String targetLine = getSchemaLine(xml);
1580
        System.out.println("before get target line");
1581
        // to see if the second line contain some keywords
1582
        if (targetLine != null
1583
                && (targetLine.indexOf(SCHEMALOCATIONKEYWORD) != -1 || targetLine
1584
                        .indexOf(NONAMESPACELOCATION) != -1)) {
1585
            // if contains schema location key word, should be validate
1586
            needSchemaValidate = true;
1587
        }
1588

    
1589
        MetaCatUtil.debugMessage("Validation for schema is "
1590
                + needSchemaValidate, 10);
1591
        return needSchemaValidate;
1592

    
1593
    }
1594

    
1595
    /* check if the xml string contains key words to specify schema loocation */
1596
    private boolean needEml2Validation(StringReader xml) throws IOException
1597
    {
1598
        boolean needEml2Validate = false;
1599
        String emlNameSpace = DocumentImpl.EMLNAMESPACE;
1600
        String schemaLocationContent = null;
1601
        if (xml == null) {
1602
            MetaCatUtil.debugMessage("Validation for schema is "
1603
                    + needEml2Validate, 10);
1604
            return needEml2Validate;
1605
        }
1606
        String targetLine = getSchemaLine(xml);
1607

    
1608
        if (targetLine != null) {
1609

    
1610
            int startIndex = targetLine.indexOf(SCHEMALOCATIONKEYWORD);
1611
            int start = 1;
1612
            int end = 1;
1613
            String schemaLocation = null;
1614
            int count = 0;
1615
            if (startIndex != -1) {
1616
                for (int i = startIndex; i < targetLine.length(); i++) {
1617
                    if (targetLine.charAt(i) == '"') {
1618
                        count++;
1619
                    }
1620
                    if (targetLine.charAt(i) == '"' && count == 1) {
1621
                        start = i;
1622
                    }
1623
                    if (targetLine.charAt(i) == '"' && count == 2) {
1624
                        end = i;
1625
                        break;
1626
                    }
1627
                }
1628
            }
1629
            schemaLocation = targetLine.substring(start + 1, end);
1630
            MetaCatUtil.debugMessage("schemaLocation in xml is: "
1631
                    + schemaLocation, 30);
1632
            if (schemaLocation.indexOf(emlNameSpace) != -1) {
1633
                needEml2Validate = true;
1634
            }
1635
        }
1636

    
1637
        MetaCatUtil.debugMessage("Validation for eml is " + needEml2Validate,
1638
                10);
1639
        return needEml2Validate;
1640

    
1641
    }
1642

    
1643
    private String getSchemaLine(StringReader xml) throws IOException
1644
    {
1645
        // find the line
1646
        String secondLine = null;
1647
        int count = 0;
1648
        int endIndex = 0;
1649
        int startIndex = 0;
1650
        final int TARGETNUM = 2;
1651
        StringBuffer buffer = new StringBuffer();
1652
        boolean comment = false;
1653
        char thirdPreviousCharacter = '?';
1654
        char secondPreviousCharacter = '?';
1655
        char previousCharacter = '?';
1656
        char currentCharacter = '?';
1657

    
1658
        while ((currentCharacter = (char) xml.read()) != -1) {
1659
            //in a comment
1660
            if (currentCharacter == '-' && previousCharacter == '-'
1661
                    && secondPreviousCharacter == '!'
1662
                    && thirdPreviousCharacter == '<') {
1663
                comment = true;
1664
            }
1665
            //out of comment
1666
            if (comment && currentCharacter == '>' && previousCharacter == '-'
1667
                    && secondPreviousCharacter == '-') {
1668
                comment = false;
1669
            }
1670

    
1671
            //this is not comment
1672
            if (currentCharacter != '!' && previousCharacter == '<' && !comment) {
1673
                count++;
1674
            }
1675
            // get target line
1676
            if (count == TARGETNUM && currentCharacter != '>') {
1677
                buffer.append(currentCharacter);
1678
            }
1679
            if (count == TARGETNUM && currentCharacter == '>') {
1680
                break;
1681
            }
1682
            thirdPreviousCharacter = secondPreviousCharacter;
1683
            secondPreviousCharacter = previousCharacter;
1684
            previousCharacter = currentCharacter;
1685

    
1686
        }
1687
        secondLine = buffer.toString();
1688
        MetaCatUtil
1689
                .debugMessage("the second line string is: " + secondLine, 25);
1690
        xml.reset();
1691
        return secondLine;
1692
    }
1693

    
1694
    /**
1695
     * Handle the database delete request and delete an XML document from the
1696
     * database connection
1697
     */
1698
    private void handleDeleteAction(PrintWriter out, Hashtable params,
1699
            HttpServletResponse response, String user, String[] groups)
1700
    {
1701

    
1702
        String[] docid = (String[]) params.get("docid");
1703

    
1704
        // delete the document from the database
1705
        try {
1706

    
1707
            // NOTE -- NEED TO TEST HERE
1708
            // FOR EXISTENCE OF DOCID PARAM
1709
            // BEFORE ACCESSING ARRAY
1710
            try {
1711
                DocumentImpl.delete(docid[0], user, groups);
1712
                response.setContentType("text/xml");
1713
                out.println("<?xml version=\"1.0\"?>");
1714
                out.println("<success>");
1715
                out.println("Document deleted.");
1716
                out.println("</success>");
1717
            } catch (AccessionNumberException ane) {
1718
                response.setContentType("text/xml");
1719
                out.println("<?xml version=\"1.0\"?>");
1720
                out.println("<error>");
1721
                out.println("Error deleting document!!!");
1722
                out.println(ane.getMessage());
1723
                out.println("</error>");
1724
            }
1725
        } catch (Exception e) {
1726
            response.setContentType("text/xml");
1727
            out.println("<?xml version=\"1.0\"?>");
1728
            out.println("<error>");
1729
            out.println(e.getMessage());
1730
            out.println("</error>");
1731
        }
1732
    }
1733

    
1734
    /**
1735
     * Handle the validation request and return the results to the requestor
1736
     */
1737
    private void handleValidateAction(PrintWriter out, Hashtable params)
1738
    {
1739

    
1740
        // Get the document indicated
1741
        String valtext = null;
1742
        DBConnection dbConn = null;
1743
        int serialNumber = -1;
1744

    
1745
        try {
1746
            valtext = ((String[]) params.get("valtext"))[0];
1747
        } catch (Exception nullpe) {
1748

    
1749
            String docid = null;
1750
            try {
1751
                // Find the document id number
1752
                docid = ((String[]) params.get("docid"))[0];
1753

    
1754
                // Get the document indicated from the db
1755
                DocumentImpl xmldoc = new DocumentImpl(docid);
1756
                valtext = xmldoc.toString();
1757

    
1758
            } catch (NullPointerException npe) {
1759

    
1760
                out.println("<error>Error getting document ID: " + docid
1761
                        + "</error>");
1762
                //if ( conn != null ) { util.returnConnection(conn); }
1763
                return;
1764
            } catch (Exception e) {
1765

    
1766
                out.println(e.getMessage());
1767
            }
1768
        }
1769

    
1770
        try {
1771
            // get a connection from the pool
1772
            dbConn = DBConnectionPool
1773
                    .getDBConnection("MetaCatServlet.handleValidateAction");
1774
            serialNumber = dbConn.getCheckOutSerialNumber();
1775
            DBValidate valobj = new DBValidate(saxparser, dbConn);
1776
            boolean valid = valobj.validateString(valtext);
1777

    
1778
            // set content type and other response header fields first
1779

    
1780
            out.println(valobj.returnErrors());
1781

    
1782
        } catch (NullPointerException npe2) {
1783
            // set content type and other response header fields first
1784

    
1785
            out.println("<error>Error validating document.</error>");
1786
        } catch (Exception e) {
1787

    
1788
            out.println(e.getMessage());
1789
        } finally {
1790
            // Return db connection
1791
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1792
        }
1793
    }
1794

    
1795
    /**
1796
     * Handle "getrevsionanddoctype" action Given a docid, return it's current
1797
     * revision and doctype from data base The output is String look like
1798
     * "rev;doctype"
1799
     */
1800
    private void handleGetRevisionAndDocTypeAction(PrintWriter out,
1801
            Hashtable params)
1802
    {
1803
        // To store doc parameter
1804
        String[] docs = new String[10];
1805
        // Store a single doc id
1806
        String givenDocId = null;
1807
        // Get docid from parameters
1808
        if (params.containsKey("docid")) {
1809
            docs = (String[]) params.get("docid");
1810
        }
1811
        // Get first docid form string array
1812
        givenDocId = docs[0];
1813

    
1814
        try {
1815
            // Make sure there is a docid
1816
            if (givenDocId == null || givenDocId.equals("")) { throw new Exception(
1817
                    "User didn't specify docid!"); }//if
1818

    
1819
            // Create a DBUtil object
1820
            DBUtil dbutil = new DBUtil();
1821
            // Get a rev and doctype
1822
            String revAndDocType = dbutil
1823
                    .getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
1824
            out.println(revAndDocType);
1825

    
1826
        } catch (Exception e) {
1827
            // Handle exception
1828
            out.println("<?xml version=\"1.0\"?>");
1829
            out.println("<error>");
1830
            out.println(e.getMessage());
1831
            out.println("</error>");
1832
        }
1833

    
1834
    }
1835

    
1836
    /**
1837
     * Handle "getaccesscontrol" action. Read Access Control List from db
1838
     * connection in XML format
1839
     */
1840
    private void handleGetAccessControlAction(PrintWriter out,
1841
            Hashtable params, HttpServletResponse response, String username,
1842
            String[] groupnames)
1843
    {
1844
        DBConnection dbConn = null;
1845
        int serialNumber = -1;
1846
        String docid = ((String[]) params.get("docid"))[0];
1847

    
1848
        try {
1849

    
1850
            // get connection from the pool
1851
            dbConn = DBConnectionPool
1852
                    .getDBConnection("MetaCatServlet.handleGetAccessControlAction");
1853
            serialNumber = dbConn.getCheckOutSerialNumber();
1854
            AccessControlList aclobj = new AccessControlList(dbConn);
1855
            String acltext = aclobj.getACL(docid, username, groupnames);
1856
            out.println(acltext);
1857

    
1858
        } catch (Exception e) {
1859
            out.println("<?xml version=\"1.0\"?>");
1860
            out.println("<error>");
1861
            out.println(e.getMessage());
1862
            out.println("</error>");
1863
        } finally {
1864
            // Retrun db connection to pool
1865
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1866
        }
1867
    }
1868

    
1869
    /**
1870
     * Handle the "getprincipals" action. Read all principals from
1871
     * authentication scheme in XML format
1872
     */
1873
    private void handleGetPrincipalsAction(PrintWriter out, String user,
1874
            String password)
1875
    {
1876
        try {
1877
            AuthSession auth = new AuthSession();
1878
            String principals = auth.getPrincipals(user, password);
1879
            out.println(principals);
1880

    
1881
        } catch (Exception e) {
1882
            out.println("<?xml version=\"1.0\"?>");
1883
            out.println("<error>");
1884
            out.println(e.getMessage());
1885
            out.println("</error>");
1886
        }
1887
    }
1888

    
1889
    /**
1890
     * Handle "getdoctypes" action. Read all doctypes from db connection in XML
1891
     * format
1892
     */
1893
    private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
1894
            HttpServletResponse response)
1895
    {
1896
        try {
1897
            DBUtil dbutil = new DBUtil();
1898
            String doctypes = dbutil.readDoctypes();
1899
            out.println(doctypes);
1900
        } catch (Exception e) {
1901
            out.println("<?xml version=\"1.0\"?>");
1902
            out.println("<error>");
1903
            out.println(e.getMessage());
1904
            out.println("</error>");
1905
        }
1906
    }
1907

    
1908
    /**
1909
     * Handle the "getdtdschema" action. Read DTD or Schema file for a given
1910
     * doctype from Metacat catalog system
1911
     */
1912
    private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
1913
            HttpServletResponse response)
1914
    {
1915

    
1916
        String doctype = null;
1917
        String[] doctypeArr = (String[]) params.get("doctype");
1918

    
1919
        // get only the first doctype specified in the list of doctypes
1920
        // it could be done for all doctypes in that list
1921
        if (doctypeArr != null) {
1922
            doctype = ((String[]) params.get("doctype"))[0];
1923
        }
1924

    
1925
        try {
1926
            DBUtil dbutil = new DBUtil();
1927
            String dtdschema = dbutil.readDTDSchema(doctype);
1928
            out.println(dtdschema);
1929

    
1930
        } catch (Exception e) {
1931
            out.println("<?xml version=\"1.0\"?>");
1932
            out.println("<error>");
1933
            out.println(e.getMessage());
1934
            out.println("</error>");
1935
        }
1936

    
1937
    }
1938

    
1939
    /**
1940
     * Handle the "getlastdocid" action. Get the latest docid with rev number
1941
     * from db connection in XML format
1942
     */
1943
    private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
1944
            HttpServletResponse response)
1945
    {
1946

    
1947
        String scope = ((String[]) params.get("scope"))[0];
1948
        if (scope == null) {
1949
            scope = ((String[]) params.get("username"))[0];
1950
        }
1951

    
1952
        try {
1953

    
1954
            DBUtil dbutil = new DBUtil();
1955
            String lastDocid = dbutil.getMaxDocid(scope);
1956
            out.println("<?xml version=\"1.0\"?>");
1957
            out.println("<lastDocid>");
1958
            out.println("  <scope>" + scope + "</scope>");
1959
            out.println("  <docid>" + lastDocid + "</docid>");
1960
            out.println("</lastDocid>");
1961

    
1962
        } catch (Exception e) {
1963
            out.println("<?xml version=\"1.0\"?>");
1964
            out.println("<error>");
1965
            out.println(e.getMessage());
1966
            out.println("</error>");
1967
        }
1968

    
1969
    }
1970

    
1971
    /**
1972
     * Handle documents passed to metacat that are encoded using the
1973
     * "multipart/form-data" mime type. This is typically used for uploading
1974
     * data files which may be binary and large.
1975
     */
1976
    private void handleMultipartForm(HttpServletRequest request,
1977
            HttpServletResponse response)
1978
    {
1979
        PrintWriter out = null;
1980
        String action = null;
1981

    
1982
        // Parse the multipart form, and save the parameters in a Hashtable and
1983
        // save the FileParts in a hashtable
1984

    
1985
        Hashtable params = new Hashtable();
1986
        Hashtable fileList = new Hashtable();
1987
        int sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit")))
1988
                .intValue();
1989
        MetaCatUtil.debugMessage(
1990
                "The limit size of data file is: " + sizeLimit, 50);
1991

    
1992
        try {
1993
            // MBJ: need to put filesize limit in Metacat config
1994
            // (metacat.properties)
1995
            MultipartParser mp = new MultipartParser(request,
1996
                    sizeLimit * 1024 * 1024);
1997
            Part part;
1998
            while ((part = mp.readNextPart()) != null) {
1999
                String name = part.getName();
2000

    
2001
                if (part.isParam()) {
2002
                    // it's a parameter part
2003
                    ParamPart paramPart = (ParamPart) part;
2004
                    String value = paramPart.getStringValue();
2005
                    params.put(name, value);
2006
                    if (name.equals("action")) {
2007
                        action = value;
2008
                    }
2009
                } else if (part.isFile()) {
2010
                    // it's a file part
2011
                    FilePart filePart = (FilePart) part;
2012
                    fileList.put(name, filePart);
2013

    
2014
                    // Stop once the first file part is found, otherwise going
2015
                    // onto the
2016
                    // next part prevents access to the file contents. So...for
2017
                    // upload
2018
                    // to work, the datafile must be the last part
2019
                    break;
2020
                }
2021
            }
2022
        } catch (IOException ioe) {
2023
            try {
2024
                out = response.getWriter();
2025
            } catch (IOException ioe2) {
2026
                System.err
2027
                        .println("Fatal Error: couldn't get response output stream.");
2028
            }
2029
            out.println("<?xml version=\"1.0\"?>");
2030
            out.println("<error>");
2031
            out.println("Error: problem reading multipart data.");
2032
            out.println("</error>");
2033
        }
2034

    
2035
        // Get the session information
2036
        String username = null;
2037
        String password = null;
2038
        String[] groupnames = null;
2039
        String sess_id = null;
2040

    
2041
        // be aware of session expiration on every request
2042
        HttpSession sess = request.getSession(true);
2043
        if (sess.isNew()) {
2044
            // session expired or has not been stored b/w user requests
2045
            username = "public";
2046
            sess.setAttribute("username", username);
2047
        } else {
2048
            username = (String) sess.getAttribute("username");
2049
            password = (String) sess.getAttribute("password");
2050
            groupnames = (String[]) sess.getAttribute("groupnames");
2051
            try {
2052
                sess_id = (String) sess.getId();
2053
            } catch (IllegalStateException ise) {
2054
                System.out
2055
                        .println("error in  handleMultipartForm: this shouldn't "
2056
                                + "happen: the session should be valid: "
2057
                                + ise.getMessage());
2058
            }
2059
        }
2060

    
2061
        // Get the out stream
2062
        try {
2063
            out = response.getWriter();
2064
        } catch (IOException ioe2) {
2065
            MetaCatUtil.debugMessage("Fatal Error: couldn't get response "
2066
                    + "output stream.", 30);
2067
        }
2068

    
2069
        if (action.equals("upload")) {
2070
            if (username != null && !username.equals("public")) {
2071
                handleUploadAction(request, out, params, fileList, username,
2072
                        groupnames);
2073
            } else {
2074

    
2075
                out.println("<?xml version=\"1.0\"?>");
2076
                out.println("<error>");
2077
                out.println("Permission denied for " + action);
2078
                out.println("</error>");
2079
            }
2080
        } else {
2081
            /*
2082
             * try { out = response.getWriter(); } catch (IOException ioe2) {
2083
             * System.err.println("Fatal Error: couldn't get response output
2084
             * stream.");
2085
             */
2086
            out.println("<?xml version=\"1.0\"?>");
2087
            out.println("<error>");
2088
            out.println(
2089
                    "Error: action not registered.  Please report this error.");
2090
            out.println("</error>");
2091
        }
2092
        out.close();
2093
    }
2094

    
2095
    /**
2096
     * Handle the upload action by saving the attached file to disk and
2097
     * registering it in the Metacat db
2098
     */
2099
    private void handleUploadAction(HttpServletRequest request,
2100
            PrintWriter out, Hashtable params, Hashtable fileList,
2101
            String username, String[] groupnames)
2102
    {
2103
        //PrintWriter out = null;
2104
        //Connection conn = null;
2105
        String action = null;
2106
        String docid = null;
2107

    
2108
        /*
2109
         * response.setContentType("text/xml"); try { out =
2110
         * response.getWriter(); } catch (IOException ioe2) {
2111
         * System.err.println("Fatal Error: couldn't get response output
2112
         * stream.");
2113
         */
2114

    
2115
        if (params.containsKey("docid")) {
2116
            docid = (String) params.get("docid");
2117
        }
2118

    
2119
        // Make sure we have a docid and datafile
2120
        if (docid != null && fileList.containsKey("datafile")) {
2121

    
2122
            // Get a reference to the file part of the form
2123
            FilePart filePart = (FilePart) fileList.get("datafile");
2124
            String fileName = filePart.getFileName();
2125
            MetaCatUtil.debugMessage("Uploading filename: " + fileName, 10);
2126

    
2127
            // Check if the right file existed in the uploaded data
2128
            if (fileName != null) {
2129

    
2130
                try {
2131
                    //MetaCatUtil.debugMessage("Upload datafile " + docid
2132
                    // +"...", 10);
2133
                    //If document get lock data file grant
2134
                    if (DocumentImpl.getDataFileLockGrant(docid)) {
2135
                        // register the file in the database (which generates
2136
                        // an exception
2137
                        //if the docid is not acceptable or other untoward
2138
                        // things happen
2139
                        DocumentImpl.registerDocument(fileName, "BIN", docid,
2140
                                username);
2141

    
2142
                        // Save the data file to disk using "docid" as the name
2143
                        dataDirectory.mkdirs();
2144
                        File newFile = new File(dataDirectory, docid);
2145
                        long size = filePart.writeTo(newFile);
2146

    
2147
                        // Force replication this data file
2148
                        // To data file, "insert" and update is same
2149
                        // The fourth parameter is null. Because it is
2150
                        // notification server
2151
                        // and this method is in MetaCatServerlet. It is
2152
                        // original command,
2153
                        // not get force replication info from another metacat
2154
                        ForceReplicationHandler frh = new ForceReplicationHandler(
2155
                                docid, "insert", false, null);
2156

    
2157
                        // set content type and other response header fields
2158
                        // first
2159
                        out.println("<?xml version=\"1.0\"?>");
2160
                        out.println("<success>");
2161
                        out.println("<docid>" + docid + "</docid>");
2162
                        out.println("<size>" + size + "</size>");
2163
                        out.println("</success>");
2164
                    }
2165

    
2166
                } catch (Exception e) {
2167
                    out.println("<?xml version=\"1.0\"?>");
2168
                    out.println("<error>");
2169
                    out.println(e.getMessage());
2170
                    out.println("</error>");
2171
                }
2172
            } else {
2173
                // the field did not contain a file
2174
                out.println("<?xml version=\"1.0\"?>");
2175
                out.println("<error>");
2176
                out.println("The uploaded data did not contain a valid file.");
2177
                out.println("</error>");
2178
            }
2179
        } else {
2180
            // Error bcse docid missing or file missing
2181
            out.println("<?xml version=\"1.0\"?>");
2182
            out.println("<error>");
2183
            out.println("The uploaded data did not contain a valid docid "
2184
                    + "or valid file.");
2185
            out.println("</error>");
2186
        }
2187
    }
2188

    
2189
    /*
2190
     * A method to handle set access action
2191
     */
2192
    private void handleSetAccessAction(PrintWriter out, Hashtable params,
2193
            String username)
2194
    {
2195
        String[] docList = null;
2196
        String[] principalList = null;
2197
        String[] permissionList = null;
2198
        String[] permTypeList = null;
2199
        String[] permOrderList = null;
2200
        String permission = null;
2201
        String permType = null;
2202
        String permOrder = null;
2203
        Vector errorList = new Vector();
2204
        String error = null;
2205
        Vector successList = new Vector();
2206
        String success = null;
2207

    
2208
        // Get parameters
2209
        if (params.containsKey("docid")) {
2210
            docList = (String[]) params.get("docid");
2211
        }
2212
        if (params.containsKey("principal")) {
2213
            principalList = (String[]) params.get("principal");
2214
        }
2215
        if (params.containsKey("permission")) {
2216
            permissionList = (String[]) params.get("permission");
2217

    
2218
        }
2219
        if (params.containsKey("permType")) {
2220
            permTypeList = (String[]) params.get("permType");
2221

    
2222
        }
2223
        if (params.containsKey("permOrder")) {
2224
            permOrderList = (String[]) params.get("permOrder");
2225

    
2226
        }
2227

    
2228
        // Make sure the parameter is not null
2229
        if (docList == null || principalList == null || permTypeList == null
2230
                || permissionList == null) {
2231
            error = "Please check your parameter list, it should look like: "
2232
                    + "?action=setaccess&docid=pipeline.1.1&principal=public"
2233
                    + "&permission=read&permType=allow&permOrder=allowFirst";
2234
            errorList.addElement(error);
2235
            outputResponse(successList, errorList, out);
2236
            return;
2237
        }
2238

    
2239
        // Only select first element for permission, type and order
2240
        permission = permissionList[0];
2241
        permType = permTypeList[0];
2242
        if (permOrderList != null) {
2243
            permOrder = permOrderList[0];
2244
        }
2245

    
2246
        // Get package doctype set
2247
        Vector packageSet = MetaCatUtil.getOptionList(MetaCatUtil
2248
                .getOption("packagedoctypeset"));
2249
        //debug
2250
        if (packageSet != null) {
2251
            for (int i = 0; i < packageSet.size(); i++) {
2252
                MetaCatUtil.debugMessage("doctype in package set: "
2253
                        + (String) packageSet.elementAt(i), 34);
2254
            }
2255
        }
2256

    
2257
        // handle every accessionNumber
2258
        for (int i = 0; i < docList.length; i++) {
2259
            String accessionNumber = docList[i];
2260
            String owner = null;
2261
            String publicId = null;
2262
            // Get document owner and public id
2263
            try {
2264
                owner = getFieldValueForDoc(accessionNumber, "user_owner");
2265
                publicId = getFieldValueForDoc(accessionNumber, "doctype");
2266
            } catch (Exception e) {
2267
                MetaCatUtil.debugMessage("Error in handleSetAccessAction: "
2268
                        + e.getMessage(), 30);
2269
                error = "Error in set access control for document - "
2270
                        + accessionNumber + e.getMessage();
2271
                errorList.addElement(error);
2272
                continue;
2273
            }
2274
            //check if user is the owner. Only owner can do owner
2275
            if (username == null || owner == null || !username.equals(owner)) {
2276
                error = "User - " + username
2277
                        + " does not have permission to set "
2278
                        + "access control for docid - " + accessionNumber;
2279
                errorList.addElement(error);
2280
                continue;
2281
            }
2282

    
2283
            // If docid publicid is BIN data file or other beta4, 6 package
2284
            // document
2285
            // we could not do set access control. Because we don't want
2286
            // inconsistent
2287
            // to its access docuemnt
2288
            if (publicId != null && packageSet != null
2289
                    && packageSet.contains(publicId)) {
2290
                error = "Could not set access control to document "
2291
                        + accessionNumber
2292
                        + "because it is in a pakcage and it has a access file for it";
2293
                errorList.addElement(error);
2294
                continue;
2295
            }
2296

    
2297
            // for every principle
2298
            for (int j = 0; j < principalList.length; j++) {
2299
                String principal = principalList[j];
2300
                try {
2301
                    //insert permission
2302
                    AccessControlForSingleFile accessControl = new AccessControlForSingleFile(
2303
                            accessionNumber, principal, permission, permType,
2304
                            permOrder);
2305
                    accessControl.insertPermissions();
2306
                    success = "Set access control to document "
2307
                            + accessionNumber + " successfully";
2308
                    successList.addElement(success);
2309
                } catch (Exception ee) {
2310
                    MetaCatUtil.debugMessage(
2311
                            "Erorr in handleSetAccessAction2: "
2312
                                    + ee.getMessage(), 30);
2313
                    error = "Faild to set access control for document "
2314
                            + accessionNumber + " because " + ee.getMessage();
2315
                    errorList.addElement(error);
2316
                    continue;
2317
                }
2318
            }
2319
        }
2320
        outputResponse(successList, errorList, out);
2321
    }
2322

    
2323
    /*
2324
     * A method try to determin a docid's public id, if couldn't find null will
2325
     * be returned.
2326
     */
2327
    private String getFieldValueForDoc(String accessionNumber, String fieldName)
2328
            throws Exception
2329
    {
2330
        if (accessionNumber == null || accessionNumber.equals("")
2331
                || fieldName == null || fieldName.equals("")) { throw new Exception(
2332
                "Docid or field name was not specified"); }
2333

    
2334
        PreparedStatement pstmt = null;
2335
        ResultSet rs = null;
2336
        String fieldValue = null;
2337
        String docId = null;
2338
        DBConnection conn = null;
2339
        int serialNumber = -1;
2340

    
2341
        // get rid of revision if access number has
2342
        docId = MetaCatUtil.getDocIdFromString(accessionNumber);
2343
        try {
2344
            //check out DBConnection
2345
            conn = DBConnectionPool
2346
                    .getDBConnection("MetaCatServlet.getPublicIdForDoc");
2347
            serialNumber = conn.getCheckOutSerialNumber();
2348
            pstmt = conn.prepareStatement("SELECT " + fieldName
2349
                    + " FROM xml_documents " + "WHERE docid = ? ");
2350

    
2351
            pstmt.setString(1, docId);
2352
            pstmt.execute();
2353
            rs = pstmt.getResultSet();
2354
            boolean hasRow = rs.next();
2355
            int perm = 0;
2356
            if (hasRow) {
2357
                fieldValue = rs.getString(1);
2358
            } else {
2359
                throw new Exception("Could not find document: "
2360
                        + accessionNumber);
2361
            }
2362
        } catch (Exception e) {
2363
            MetaCatUtil.debugMessage(
2364
                    "Exception in MetacatServlet.getPublicIdForDoc: "
2365
                            + e.getMessage(), 30);
2366
            throw e;
2367
        } finally {
2368
            try {
2369
                rs.close();
2370
                pstmt.close();
2371

    
2372
            } finally {
2373
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2374
            }
2375
        }
2376
        return fieldValue;
2377
    }
2378

    
2379
    /*
2380
     * A method to output setAccess action result
2381
     */
2382
    private void outputResponse(Vector successList, Vector errorList,
2383
            PrintWriter out)
2384
    {
2385
        boolean error = false;
2386
        boolean success = false;
2387
        // Output prolog
2388
        out.println(PROLOG);
2389
        // output success message
2390
        if (successList != null) {
2391
            for (int i = 0; i < successList.size(); i++) {
2392
                out.println(SUCCESS);
2393
                out.println((String) successList.elementAt(i));
2394
                out.println(SUCCESSCLOSE);
2395
                success = true;
2396
            }
2397
        }
2398
        // output error message
2399
        if (errorList != null) {
2400
            for (int i = 0; i < errorList.size(); i++) {
2401
                out.println(ERROR);
2402
                out.println((String) errorList.elementAt(i));
2403
                out.println(ERRORCLOSE);
2404
                error = true;
2405
            }
2406
        }
2407

    
2408
        // if no error and no success info, send a error that nothing happened
2409
        if (!error && !success) {
2410
            out.println(ERROR);
2411
            out.println("Nothing happend for setaccess action");
2412
            out.println(ERRORCLOSE);
2413
        }
2414
    }
2415
}
(41-41/61)