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: 2005-11-16 17:27:26 -0800 (Wed, 16 Nov 2005) $'
11
 * '$Revision: 2752 $'
12
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
 */
27

    
28
package edu.ucsb.nceas.metacat;
29

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

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

    
61
import org.apache.log4j.Logger;
62
import org.apache.log4j.PropertyConfigurator;
63
import org.ecoinformatics.eml.EMLParser;
64

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

    
70
import edu.ucsb.nceas.utilities.Options;
71

    
72
/**
73
 * A metadata catalog server implemented as a Java Servlet
74
 *
75
 * <p>
76
 * Valid parameters are: <br>
77
 * action=query -- query the values of all elements and attributes and return a
78
 * result set of nodes <br>
79
 * action=squery -- structured query (see pathquery.dtd) <br>
80
 * action= -- export a zip format for data packadge <br>
81
 * action=read -- read any metadata/data file from Metacat and from Internet
82
 * <br>
83
 * action=insert -- insert an XML document into the database store <br>
84
 * action=update -- update an XML document that is in the database store <br>
85
 * action=delete -- delete an XML document from the database store <br>
86
 * action=validate -- vallidate the xml contained in valtext <br>
87
 * doctype -- document type list returned by the query (publicID) <br>
88
 * qformat=xml -- display resultset from query in XML <br>
89
 * qformat=html -- display resultset from query in HTML <br>
90
 * qformat=zip -- zip resultset from query <br>
91
 * docid=34 -- display the document with the document ID number 34 <br>
92
 * doctext -- XML text of the document to load into the database <br>
93
 * acltext -- XML access text for a document to load into the database <br>
94
 * dtdtext -- XML DTD text for a new DTD to load into Metacat XML Catalog <br>
95
 * query -- actual query text (to go with 'action=query' or 'action=squery')
96
 * <br>
97
 * valtext -- XML text to be validated <br>
98
 * action=getaccesscontrol -- retrieve acl info for Metacat document <br>
99
 * action=getdoctypes -- retrieve all doctypes (publicID) <br>
100
 * action=getdtdschema -- retrieve a DTD or Schema file <br>
101
 * action=getdataguide -- retrieve a Data Guide <br>
102
 * action=getprincipals -- retrieve a list of principals in XML <br>
103
 * datadoc -- data document name (id) <br>
104
 * action=getlog -- get a report of events that have occurred in the system<br>
105
 * ipAddress --  filter on one or more IP addresses<br>
106
 * principal -- filter on one or more principals (LDAP DN syntax)<br>
107
 * docid -- filter on one or more document identifiers (with revision)<br>
108
 * event -- filter on event type (e.g., read, insert, update, delete)<br>
109
 * start -- filter out events before the start date-time<br>
110
 * end -- filter out events before the end date-time<br>
111
 * <p>
112
 * The particular combination of parameters that are valid for each particular
113
 * action value is quite specific. This documentation will be reorganized to
114
 * reflect this information.
115
 */
116
public class MetaCatServlet extends HttpServlet
117
{
118
    private static Hashtable sessionHash = new Hashtable();
119
    private static Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
120
    private Timer timer = null;
121
    
122
    // Constants -- these should be final in a servlet
123
    private static final String PROLOG = "<?xml version=\"1.0\"?>";
124
    private static final String SUCCESS = "<success>";
125
    private static final String SUCCESSCLOSE = "</success>";
126
    private static final String ERROR = "<error>";
127
    private static final String ERRORCLOSE = "</error>";
128
    public static final String SCHEMALOCATIONKEYWORD = ":schemaLocation";
129
    public static final String NONAMESPACELOCATION = ":noNamespaceSchemaLocation";
130
    public static final String NAMESPACEKEYWORD = "xmlns";
131
    public static final String EML2KEYWORD = ":eml";
132
    public static final String XMLFORMAT = "xml";
133
    private static final String CONFIG_DIR = "WEB-INF";
134
    private static final String CONFIG_NAME = "metacat.properties"; 
135
    
136
    /**
137
     * Initialize the servlet by creating appropriate database connections
138
     */
139
    public void init(ServletConfig config) throws ServletException
140
    {
141
        try {
142
            super.init(config);
143
            ServletContext context = config.getServletContext();
144

    
145
            // Initialize the properties file for our options
146
            String dirPath = context.getRealPath(CONFIG_DIR);
147
            File propertyFile = new File(dirPath, CONFIG_NAME);
148

    
149
            String LOG_CONFIG_NAME = dirPath + "/log4j.properties";
150
            PropertyConfigurator.configureAndWatch(LOG_CONFIG_NAME);
151
            
152
            Options options = null;
153
            try {
154
                options = Options.initialize(propertyFile);
155
                MetaCatUtil.printMessage("Options configured: "
156
                        + options.getOption("configured"));
157
            } catch (IOException ioe) {
158
                logMetacat.error("Error in loading options: "
159
                        + ioe.getMessage());
160
            }
161

    
162
            MetaCatUtil util = new MetaCatUtil();
163

    
164
            //initialize DBConnection pool
165
            DBConnectionPool connPool = DBConnectionPool.getInstance();
166
            
167
            // Index the paths specified in the metacat.properties
168
            checkIndexPaths();
169

    
170
            // initiate the indexing Queue
171
            IndexingQueue.getInstance();
172
            
173
            // start the IndexingThread if indexingTimerTaskTime more than 0. 
174
            // It will index all the documents not yet indexed in the database             
175
            int indexingTimerTaskTime = Integer.parseInt(MetaCatUtil.getOption("indexingTimerTaskTime"));
176
            if(indexingTimerTaskTime > 0){
177
            	timer = new Timer();
178
            	timer.schedule(new IndexingTimerTask(), 0, indexingTimerTaskTime);
179
            }
180
            
181
            MetaCatUtil.printMessage("Metacat (" + Version.getVersion()
182
                               + ") initialized.");
183

    
184
        } catch (ServletException ex) {
185
            throw ex;
186
        } catch (SQLException e) {
187
            logMetacat.error("Error in MetacatServlet.init: "
188
                    + e.getMessage());
189
        }
190
    }
191

    
192
    /**
193
     * Close all db connections from the pool
194
     */
195
    public void destroy()
196
    {
197
        // Close all db connection
198
        System.out.println("Destroying MetacatServlet");
199
        DBConnectionPool.release();
200
        timer.cancel();
201
    }
202

    
203
    /** Handle "GET" method requests from HTTP clients */
204
    public void doGet(HttpServletRequest request, HttpServletResponse response)
205
            throws ServletException, IOException
206
    {
207

    
208
        // Process the data and send back the response
209
        handleGetOrPost(request, response);
210
    }
211

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

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

    
221
    /**
222
     * Index the paths specified in the metacat.properties
223
     */
224
    private void checkIndexPaths(){
225
        MetaCatUtil.pathsForIndexing
226
            = MetaCatUtil.getOptionList(MetaCatUtil.getOption("indexed_paths"));
227
    
228
        if (MetaCatUtil.pathsForIndexing != null) {
229
    
230
            MetaCatUtil.printMessage("Indexing paths specified in metacat.properties....");
231
    
232
            DBConnection conn = null;
233
            int serialNumber = -1;
234
            PreparedStatement pstmt = null;
235
            PreparedStatement pstmt1 = null;
236
            ResultSet rs = null;
237
    
238
            for (int i = 0; i < MetaCatUtil.pathsForIndexing.size(); i++) {
239
                logMetacat.info("Checking if '"
240
                           + (String) MetaCatUtil.pathsForIndexing.elementAt(i)
241
                           + "' is indexed.... ");
242
    
243
                try {
244
                    //check out DBConnection
245
                    conn = DBConnectionPool.
246
                        getDBConnection("MetaCatServlet.checkIndexPaths");
247
                    serialNumber = conn.getCheckOutSerialNumber();
248
    
249
                    pstmt = conn.prepareStatement(
250
                        "SELECT * FROM xml_path_index " + "WHERE path = ?");
251
                    pstmt.setString(1, (String) MetaCatUtil.pathsForIndexing
252
                                    .elementAt(i));
253
    
254
                    pstmt.execute();
255
                    rs = pstmt.getResultSet();
256
    
257
                    if (!rs.next()) {
258
                        logMetacat.info(".....not indexed yet.");
259
                        rs.close();
260
                        pstmt.close();
261
                        conn.increaseUsageCount(1);
262
    
263
                        logMetacat.debug(
264
                              "Inserting following path in xml_path_index: "
265
                              + (String)MetaCatUtil.pathsForIndexing
266
                                                   .elementAt(i));
267
    
268
                        pstmt = conn.prepareStatement("SELECT DISTINCT n.docid, "
269
                              + "n.nodedata, n.nodedatanumerical, n.parentnodeid"
270
                              + " FROM xml_nodes n, xml_index i WHERE"
271
                              + " i.path = ? and n.parentnodeid=i.nodeid and"
272
                              + " n.nodetype LIKE 'TEXT' order by n.parentnodeid");
273
                        pstmt.setString(1, (String) MetaCatUtil.
274
                                        pathsForIndexing.elementAt(i));
275
                        pstmt.execute();
276
                        rs = pstmt.getResultSet();
277
    
278
                        int count = 0;
279
                        logMetacat.debug(
280
                                       "Executed the select statement for: "
281
                                       + (String) MetaCatUtil.pathsForIndexing
282
                                         .elementAt(i));
283
    
284
                        try {
285
                            while (rs.next()) {
286
    
287
                                String docid = rs.getString(1);
288
                                String nodedata = rs.getString(2);
289
                                float nodedatanumerical = rs.getFloat(3);
290
                                int parentnodeid = rs.getInt(4);
291
    
292
                                if (!nodedata.trim().equals("")) {
293
                                    pstmt1 = conn.prepareStatement(
294
                                        "INSERT INTO xml_path_index"
295
                                        + " (docid, path, nodedata, "
296
                                        + "nodedatanumerical, parentnodeid)"
297
                                        + " VALUES (?, ?, ?, ?, ?)");
298
    
299
                                    pstmt1.setString(1, docid);
300
                                    pstmt1.setString(2, (String) MetaCatUtil.
301
                                                pathsForIndexing.elementAt(i));
302
                                    pstmt1.setString(3, nodedata);
303
                                    pstmt1.setFloat(4, nodedatanumerical);
304
                                    pstmt1.setInt(5, parentnodeid);
305
    
306
                                    pstmt1.execute();
307
                                    pstmt1.close();
308
    
309
                                    count++;
310
    
311
                                }
312
                            }
313
                        }
314
                        catch (Exception e) {
315
                            System.out.println("Exception:" + e.getMessage());
316
                            e.printStackTrace();
317
                        }
318
    
319
                        rs.close();
320
                        pstmt.close();
321
                        conn.increaseUsageCount(1);
322
    
323
                        logMetacat.warn("Indexed " + count
324
                                + " records from xml_nodes for '"
325
                                + (String) MetaCatUtil.pathsForIndexing.elementAt(i)
326
                                + "'");
327
    
328
                    } else {
329
                    	logMetacat.info(".....already indexed.");
330
                    }
331
    
332
                    rs.close();
333
                    pstmt.close();
334
                    conn.increaseUsageCount(1);
335
    
336
                } catch (Exception e) {
337
                    logMetacat.error("Error in MetaCatServlet.checkIndexPaths: "
338
                                             + e.getMessage());
339
                }finally {
340
                    //check in DBonnection
341
                    DBConnectionPool.returnDBConnection(conn, serialNumber);
342
                }
343
    
344
    
345
            }
346
    
347
            MetaCatUtil.printMessage("Path Indexing Completed");
348
        }
349
    }    
350

    
351
    /**
352
     * Control servlet response depending on the action parameter specified
353
     */
354
    private void handleGetOrPost(HttpServletRequest request,
355
            HttpServletResponse response) throws ServletException, IOException
356
    {
357
        MetaCatUtil util = new MetaCatUtil();
358
       
359
        /*
360
         * logMetacat.info("Connection pool size: "
361
         * +connPool.getSizeOfDBConnectionPool(),10);
362
         * logMetacat.info("Free DBConnection number: "
363
         */
364
        //If all DBConnection in the pool are free and DBConnection pool
365
        //size is greater than initial value, shrink the connection pool
366
        //size to initial value
367
        DBConnectionPool.shrinkDBConnectionPoolSize();
368

    
369
        //Debug message to print out the method which have a busy DBConnection
370
        try {
371
            DBConnectionPool pool = DBConnectionPool.getInstance();
372
            pool.printMethodNameHavingBusyDBConnection();
373
        } catch (SQLException e) {
374
            logMetacat.error("Error in MetacatServlet.handleGetOrPost: "
375
                    + e.getMessage());
376
            e.printStackTrace();
377
        }
378

    
379
        String ctype = request.getContentType();
380
        if (ctype != null && ctype.startsWith("multipart/form-data")) {
381
            handleMultipartForm(request, response);
382
        } else {
383

    
384
            String name = null;
385
            String[] value = null;
386
            String[] docid = new String[3];
387
            Hashtable params = new Hashtable();
388
            Enumeration paramlist = request.getParameterNames();
389

    
390
            while (paramlist.hasMoreElements()) {
391

    
392
                name = (String) paramlist.nextElement();
393
                value = request.getParameterValues(name);
394

    
395
                // Decode the docid and mouse click information
396
                if (name.endsWith(".y")) {
397
                    docid[0] = name.substring(0, name.length() - 2);
398
                    params.put("docid", docid);
399
                    name = "ypos";
400
                }
401
                if (name.endsWith(".x")) {
402
                    name = "xpos";
403
                }
404

    
405
                params.put(name, value);
406
            }
407

    
408
            //handle param is emptpy
409
            if (params.isEmpty() || params == null) { return; }
410

    
411
            //if the user clicked on the input images, decode which image
412
            //was clicked then set the action.
413
            if(params.get("action") == null){
414
                PrintWriter out = response.getWriter();
415
                response.setContentType("text/xml");
416
                out.println("<?xml version=\"1.0\"?>");
417
                out.println("<error>");
418
                out.println("Action not specified");
419
                out.println("</error>");
420
                out.close();
421
                return;
422
            }
423

    
424
            String action = ((String[]) params.get("action"))[0];
425
            logMetacat.warn("Action is: " + action);
426

    
427
            // This block handles session management for the servlet
428
            // by looking up the current session information for all actions
429
            // other than "login" and "logout"
430
            String username = null;
431
            String password = null;
432
            String[] groupnames = null;
433
            String sess_id = null;
434
            name = null;
435
            
436
            // handle login action
437
            if (action.equals("login")) {
438
                PrintWriter out = response.getWriter();
439
                handleLoginAction(out, params, request, response);
440
                out.close();
441

    
442
                // handle logout action
443
            } else if (action.equals("logout")) {
444
                PrintWriter out = response.getWriter();
445
                handleLogoutAction(out, params, request, response);
446
                out.close();
447

    
448
                // handle shrink DBConnection request
449
            } else if (action.equals("shrink")) {
450
                PrintWriter out = response.getWriter();
451
                boolean success = false;
452
                //If all DBConnection in the pool are free and DBConnection
453
                // pool
454
                //size is greater than initial value, shrink the connection
455
                // pool
456
                //size to initial value
457
                success = DBConnectionPool.shrinkConnectionPoolSize();
458
                if (success) {
459
                    //if successfully shrink the pool size to initial value
460
                    out.println("DBConnection Pool shrunk successfully.");
461
                }//if
462
                else {
463
                    out.println("DBConnection pool not shrunk successfully.");
464
                }
465
                //close out put
466
                out.close();
467

    
468
                // aware of session expiration on every request
469
            } else {
470
                HttpSession sess = request.getSession(true);
471
                if (sess.isNew() && !params.containsKey("sessionid")) {
472
                    // session expired or has not been stored b/w user requests
473
                    logMetacat.warn(
474
                            "The session is new or no sessionid is assigned. The user is public");
475
                    username = "public";
476
                    sess.setAttribute("username", username);
477
                } else {
478
                    logMetacat.warn("The session is either old or "
479
                            + "has sessionid parameter");
480
                    try {
481
                        if (params.containsKey("sessionid")) {
482
                            sess_id = ((String[]) params.get("sessionid"))[0];
483
                            logMetacat.info("in has sessionid "
484
                                    + sess_id);
485
                            if (sessionHash.containsKey(sess_id)) {
486
                                logMetacat.info("find the id "
487
                                        + sess_id + " in hash table");
488
                                sess = (HttpSession) sessionHash.get(sess_id);
489
                            }
490
                        } else {
491
                            // we already store the session in login, so we
492
                            // don't need here
493
                            /*
494
                             * logMetacat.info("in no sessionid
495
                             * parameter ", 40); sess_id =
496
                             * (String)sess.getId();
497
                             * logMetacat.info("storing the session id "
498
                             * + sess_id + " which has username " +
499
                             * sess.getAttribute("username") + " into session
500
                             * hash in handleGetOrPost method", 35);
501
                             */
502
                        }
503
                    } catch (IllegalStateException ise) {
504
                        logMetacat.error(
505
                                "Error in handleGetOrPost: this shouldn't "
506
                                + "happen: the session should be valid: "
507
                                + ise.getMessage());
508
                    }
509

    
510
                    username = (String) sess.getAttribute("username");
511
                    logMetacat.info("The user name from session is: "
512
                            + username);
513
                    password = (String) sess.getAttribute("password");
514
                    groupnames = (String[]) sess.getAttribute("groupnames");
515
                    name = (String) sess.getAttribute("name");
516
                }
517

    
518
                //make user user username should be public
519
                if (username == null || (username.trim().equals(""))) {
520
                    username = "public";
521
                }
522
                logMetacat.warn("The user is : " + username);
523
            }
524
            // Now that we know the session is valid, we can delegate the
525
            // request
526
            // to a particular action handler
527
            if (action.equals("query")) {
528
                PrintWriter out = response.getWriter();
529
                handleQuery(out, params, response, username, groupnames,
530
                        sess_id);
531
                out.close();
532
            } else if (action.equals("squery")) {
533
                PrintWriter out = response.getWriter();
534
                if (params.containsKey("query")) {
535
                    handleSQuery(out, params, response, username, groupnames,
536
                            sess_id);
537
                    out.close();
538
                } else {
539
                    out.println(
540
                            "Illegal action squery without \"query\" parameter");
541
                    out.close();
542
                }
543
            } else if (action.equals("export")) {
544

    
545
                handleExportAction(params, response, username,
546
                        groupnames, password);
547
            } else if (action.equals("read")) {
548
                handleReadAction(params, request, response, username, password,
549
                        groupnames);
550
            } else if (action.equals("readinlinedata")) {
551
                handleReadInlineDataAction(params, request, response, username,
552
                        password, groupnames);
553
            } else if (action.equals("insert") || action.equals("update")) {
554
                PrintWriter out = response.getWriter();
555
                if ((username != null) && !username.equals("public")) {
556
                    handleInsertOrUpdateAction(request, response,
557
                            out, params, username, groupnames);
558
                } else {
559
                    response.setContentType("text/xml");
560
                    out.println("<?xml version=\"1.0\"?>");
561
                    out.println("<error>");
562
                    out.println("Permission denied for user " + username + " "
563
                            + action);
564
                    out.println("</error>");
565
                }
566
                out.close();
567
            } else if (action.equals("delete")) {
568
                PrintWriter out = response.getWriter();
569
                if ((username != null) && !username.equals("public")) {
570
                    handleDeleteAction(out, params, request, response, username,
571
                            groupnames);
572
                } else {
573
                    response.setContentType("text/xml");
574
                    out.println("<?xml version=\"1.0\"?>");
575
                    out.println("<error>");
576
                    out.println("Permission denied for " + action);
577
                    out.println("</error>");
578
                }
579
                out.close();
580
            } else if (action.equals("validate")) {
581
                PrintWriter out = response.getWriter();
582
                handleValidateAction(out, params);
583
                out.close();
584
            } else if (action.equals("setaccess")) {
585
                PrintWriter out = response.getWriter();
586
                handleSetAccessAction(out, params, username);
587
                out.close();
588
            } else if (action.equals("getaccesscontrol")) {
589
                PrintWriter out = response.getWriter();
590
                handleGetAccessControlAction(out, params, response, username,
591
                        groupnames);
592
                out.close();
593
            } else if (action.equals("getprincipals")) {
594
                PrintWriter out = response.getWriter();
595
                handleGetPrincipalsAction(out, username, password);
596
                out.close();
597
            } else if (action.equals("getdoctypes")) {
598
                PrintWriter out = response.getWriter();
599
                handleGetDoctypesAction(out, params, response);
600
                out.close();
601
            } else if (action.equals("getdtdschema")) {
602
                PrintWriter out = response.getWriter();
603
                handleGetDTDSchemaAction(out, params, response);
604
                out.close();
605
            } else if (action.equals("getlastdocid")) {
606
                PrintWriter out = response.getWriter();
607
                handleGetMaxDocidAction(out, params, response);
608
                out.close();
609
            } else if (action.equals("getrevisionanddoctype")) {
610
                PrintWriter out = response.getWriter();
611
                handleGetRevisionAndDocTypeAction(out, params);
612
                out.close();
613
            } else if (action.equals("getversion")) {
614
                response.setContentType("text/xml");
615
                PrintWriter out = response.getWriter();
616
                out.println(Version.getVersionAsXml());
617
                out.close();
618
            } else if (action.equals("getlog")) {
619
                handleGetLogAction(params, request, response, username, groupnames);
620
            } else if (action.equals("getloggedinuserinfo")) {
621
                PrintWriter out = response.getWriter();
622
                response.setContentType("text/xml");
623
                out.println("<?xml version=\"1.0\"?>");
624
                out.println("\n<user>\n");
625
                out.println("\n<username>\n");
626
                out.println(username);
627
                out.println("\n</username>\n");
628
                if(name!=null){
629
                	out.println("\n<name>\n");
630
                	out.println(name);
631
                	out.println("\n</name>\n");
632
                }
633
                if(MetaCatUtil.isAdministrator(username, groupnames)){
634
                	out.println("<isAdministrator></isAdministrator>\n");	
635
                }
636
                if(MetaCatUtil.isModerator(username, groupnames)){
637
                	out.println("<isModerator></isModerator>\n");	
638
                }
639
                out.println("\n</user>\n");
640
                out.close();
641
            } else if (action.equals("buildindex")) {
642
                handleBuildIndexAction(params, request, response, username, groupnames);
643
            } else if (action.equals("login") || action.equals("logout")) {
644
                /*
645
            } else if (action.equals("protocoltest")) {
646
                String testURL = "metacat://dev.nceas.ucsb.edu/NCEAS.897766.9";
647
                try {
648
                    testURL = ((String[]) params.get("url"))[0];
649
                } catch (Throwable t) {
650
                }
651
                String phandler = System
652
                        .getProperty("java.protocol.handler.pkgs");
653
                response.setContentType("text/html");
654
                PrintWriter out = response.getWriter();
655
                out.println("<body bgcolor=\"white\">");
656
                out.println("<p>Handler property: <code>" + phandler
657
                        + "</code></p>");
658
                out.println("<p>Starting test for:<br>");
659
                out.println("    " + testURL + "</p>");
660
                try {
661
                    URL u = new URL(testURL);
662
                    out.println("<pre>");
663
                    out.println("Protocol: " + u.getProtocol());
664
                    out.println("    Host: " + u.getHost());
665
                    out.println("    Port: " + u.getPort());
666
                    out.println("    Path: " + u.getPath());
667
                    out.println("     Ref: " + u.getRef());
668
                    String pquery = u.getQuery();
669
                    out.println("   Query: " + pquery);
670
                    out.println("  Params: ");
671
                    if (pquery != null) {
672
                        Hashtable qparams = MetaCatUtil.parseQuery(u.getQuery());
673
                        for (Enumeration en = qparams.keys(); en
674
                                .hasMoreElements();) {
675
                            String pname = (String) en.nextElement();
676
                            String pvalue = (String) qparams.get(pname);
677
                            out.println("    " + pname + ": " + pvalue);
678
                        }
679
                    }
680
                    out.println("</pre>");
681
                    out.println("</body>");
682
                    out.close();
683
                } catch (MalformedURLException mue) {
684
                    System.out.println(
685
                            "bad url from MetacatServlet.handleGetOrPost");
686
                    out.println(mue.getMessage());
687
                    mue.printStackTrace(out);
688
                    out.close();
689
                }
690
                */
691
            } else {
692
                PrintWriter out = response.getWriter();
693
                out.println("<?xml version=\"1.0\"?>");
694
                out.println("<error>");
695
                out.println(
696
                     "Error: action not registered.  Please report this error.");
697
                out.println("</error>");
698
                out.close();
699
            }
700

    
701
            //util.closeConnections();
702
            // Close the stream to the client
703
            //out.close();
704
        }
705
    }
706

    
707
    // LOGIN & LOGOUT SECTION
708
    /**
709
     * Handle the login request. Create a new session object. Do user
710
     * authentication through the session.
711
     */
712
    private void handleLoginAction(PrintWriter out, Hashtable params,
713
            HttpServletRequest request, HttpServletResponse response)
714
    {
715

    
716
        AuthSession sess = null;
717

    
718
        if(params.get("username") == null){
719
            response.setContentType("text/xml");
720
            out.println("<?xml version=\"1.0\"?>");
721
            out.println("<error>");
722
            out.println("Username not specified");
723
            out.println("</error>");
724
            return;
725
        }
726

    
727
        if(params.get("password") == null){
728
            response.setContentType("text/xml");
729
            out.println("<?xml version=\"1.0\"?>");
730
            out.println("<error>");
731
            out.println("Password not specified");
732
            out.println("</error>");
733
            return;
734
        }
735

    
736
        String un = ((String[]) params.get("username"))[0];
737
        logMetacat.warn("user " + un + " is trying to login");
738
        String pw = ((String[]) params.get("password"))[0];
739

    
740
        String qformat = "xml";
741
        if(params.get("qformat") != null){
742
            qformat = ((String[]) params.get("qformat"))[0];
743
        }
744

    
745
        try {
746
            sess = new AuthSession();
747
        } catch (Exception e) {
748
            System.out.println("error in MetacatServlet.handleLoginAction: "
749
                    + e.getMessage());
750
            out.println(e.getMessage());
751
            return;
752
        }
753
        boolean isValid = sess.authenticate(request, un, pw);
754

    
755
        //if it is authernticate is true, store the session
756
        if (isValid) {
757
            HttpSession session = sess.getSessions();
758
            String id = session.getId();
759
            logMetacat.info("Store session id " + id
760
                    + "which has username" + session.getAttribute("username")
761
                    + " into hash in login method");
762
            sessionHash.put(id, session);
763
        }
764

    
765
        // format and transform the output
766
        if (qformat.equals("xml")) {
767
            response.setContentType("text/xml");
768
            out.println(sess.getMessage());
769
        } else {
770
            try {
771
                DBTransform trans = new DBTransform();
772
                response.setContentType("text/html");
773
                trans.transformXMLDocument(sess.getMessage(),
774
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
775
                        out, null);
776
            } catch (Exception e) {
777

    
778
                logMetacat.error(
779
                        "Error in MetaCatServlet.handleLoginAction: "
780
                                + e.getMessage());
781
            }
782
        }
783
    }
784

    
785
    /**
786
     * Handle the logout request. Close the connection.
787
     */
788
    private void handleLogoutAction(PrintWriter out, Hashtable params,
789
            HttpServletRequest request, HttpServletResponse response)
790
    {
791

    
792
        String qformat = "xml";
793
        if(params.get("qformat") != null){
794
            qformat = ((String[]) params.get("qformat"))[0];
795
        }
796

    
797
        // close the connection
798
        HttpSession sess = request.getSession(false);
799
        logMetacat.info("After get session in logout request");
800
        if (sess != null) {
801
            logMetacat.info("The session id " + sess.getId()
802
                    + " will be invalidate in logout action");
803
            logMetacat.warn("The session contains user "
804
                    + sess.getAttribute("username")
805
                    + " will be invalidate in logout action");
806
            sess.invalidate();
807
        }
808

    
809
        // produce output
810
        StringBuffer output = new StringBuffer();
811
        output.append("<?xml version=\"1.0\"?>");
812
        output.append("<logout>");
813
        output.append("User logged out");
814
        output.append("</logout>");
815

    
816
        //format and transform the output
817
        if (qformat.equals("xml")) {
818
            response.setContentType("text/xml");
819
            out.println(output.toString());
820
        } else {
821
            try {
822
                DBTransform trans = new DBTransform();
823
                response.setContentType("text/html");
824
                trans.transformXMLDocument(output.toString(),
825
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
826
                        out, null);
827
            } catch (Exception e) {
828
                logMetacat.error(
829
                        "Error in MetaCatServlet.handleLogoutAction"
830
                                + e.getMessage());
831
            }
832
        }
833
    }
834

    
835
    // END OF LOGIN & LOGOUT SECTION
836

    
837
    // SQUERY & QUERY SECTION
838
    /**
839
     * Retreive the squery xml, execute it and display it
840
     *
841
     * @param out the output stream to the client
842
     * @param params the Hashtable of parameters that should be included in the
843
     *            squery.
844
     * @param response the response object linked to the client
845
     * @param conn the database connection
846
     */
847
    private void handleSQuery(PrintWriter out, Hashtable params,
848
            HttpServletResponse response, String user, String[] groups,
849
            String sessionid)
850
    {
851
        double startTime = System.currentTimeMillis() / 1000;
852
        DBQuery queryobj = new DBQuery();
853
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
854
        double outPutTime = System.currentTimeMillis() / 1000;
855
        logMetacat.warn("Total search time for action 'squery': "
856
                + (outPutTime - startTime));
857

    
858
    }
859

    
860
    /**
861
     * Create the xml query, execute it and display the results.
862
     *
863
     * @param out the output stream to the client
864
     * @param params the Hashtable of parameters that should be included in the
865
     *            squery.
866
     * @param response the response object linked to the client
867
     */
868
    private void handleQuery(PrintWriter out, Hashtable params,
869
            HttpServletResponse response, String user, String[] groups,
870
            String sessionid)
871
    {
872
        //create the query and run it
873
        String xmlquery = DBQuery.createSQuery(params);
874
        String[] queryArray = new String[1];
875
        queryArray[0] = xmlquery;
876
        params.put("query", queryArray);
877
        double startTime = System.currentTimeMillis() / 1000;
878
        DBQuery queryobj = new DBQuery();
879
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
880
        double outPutTime = System.currentTimeMillis() / 1000;
881
        logMetacat.warn("Total search time for action 'query': "
882
                + (outPutTime - startTime));
883

    
884
        //handleSQuery(out, params, response,user, groups, sessionid);
885
    }
886

    
887
    // END OF SQUERY & QUERY SECTION
888

    
889
    //Exoport section
890
    /**
891
     * Handle the "export" request of data package from Metacat in zip format
892
     *
893
     * @param params the Hashtable of HTTP request parameters
894
     * @param response the HTTP response object linked to the client
895
     * @param user the username sent the request
896
     * @param groups the user's groupnames
897
     */
898
    private void handleExportAction(Hashtable params,
899
            HttpServletResponse response,
900
            String user, String[] groups, String passWord)
901
    {
902
        // Output stream
903
        ServletOutputStream out = null;
904
        // Zip output stream
905
        ZipOutputStream zOut = null;
906
        DBQuery queryObj = null;
907

    
908
        String[] docs = new String[10];
909
        String docId = "";
910

    
911
        try {
912
            // read the params
913
            if (params.containsKey("docid")) {
914
                docs = (String[]) params.get("docid");
915
            }
916
            // Create a DBuery to handle export
917
            queryObj = new DBQuery();
918
            // Get the docid
919
            docId = docs[0];
920
            // Make sure the client specify docid
921
            if (docId == null || docId.equals("")) {
922
                response.setContentType("text/xml"); //MIME type
923
                // Get a printwriter
924
                PrintWriter pw = response.getWriter();
925
                // Send back message
926
                pw.println("<?xml version=\"1.0\"?>");
927
                pw.println("<error>");
928
                pw.println("You didn't specify requested docid");
929
                pw.println("</error>");
930
                // Close printwriter
931
                pw.close();
932
                return;
933
            }
934
            // Get output stream
935
            out = response.getOutputStream();
936
            response.setContentType("application/zip"); //MIME type
937
            response.setHeader("Content-Disposition", 
938
            		"attachment; filename=" 
939
            		+ docId + ".zip"); // Set the name of the zip file
940
            		
941
            zOut = new ZipOutputStream(out);
942
            zOut = queryObj
943
                    .getZippedPackage(docId, out, user, groups, passWord);
944
            zOut.finish(); //terminate the zip file
945
            zOut.close(); //close the zip stream
946

    
947
        } catch (Exception e) {
948
            try {
949
                response.setContentType("text/xml"); //MIME type
950
                // Send error message back
951
                if (out != null) {
952
                    PrintWriter pw = new PrintWriter(out);
953
                    pw.println("<?xml version=\"1.0\"?>");
954
                    pw.println("<error>");
955
                    pw.println(e.getMessage());
956
                    pw.println("</error>");
957
                    // Close printwriter
958
                    pw.close();
959
                    // Close output stream
960
                    out.close();
961
                }
962
                // Close zip output stream
963
                if (zOut != null) {
964
                    zOut.close();
965
                }
966
            } catch (IOException ioe) {
967
                logMetacat.error("Problem with the servlet output "
968
                        + "in MetacatServlet.handleExportAction: "
969
                        + ioe.getMessage());
970
            }
971

    
972
            logMetacat.error(
973
                    "Error in MetacatServlet.handleExportAction: "
974
                            + e.getMessage());
975
            e.printStackTrace(System.out);
976

    
977
        }
978

    
979
    }
980

    
981
    /**
982
     * In eml2 document, the xml can have inline data and data was stripped off
983
     * and store in file system. This action can be used to read inline data
984
     * only
985
     *
986
     * @param params the Hashtable of HTTP request parameters
987
     * @param response the HTTP response object linked to the client
988
     * @param user the username sent the request
989
     * @param groups the user's groupnames
990
     */
991
    private void handleReadInlineDataAction(Hashtable params,
992
            HttpServletRequest request, HttpServletResponse response,
993
            String user, String passWord, String[] groups)
994
    {
995
        String[] docs = new String[10];
996
        String inlineDataId = null;
997
        String docId = "";
998
        ServletOutputStream out = null;
999

    
1000
        try {
1001
            // read the params
1002
            if (params.containsKey("inlinedataid")) {
1003
                docs = (String[]) params.get("inlinedataid");
1004
            }
1005
            // Get the docid
1006
            inlineDataId = docs[0];
1007
            // Make sure the client specify docid
1008
            if (inlineDataId == null || inlineDataId.equals("")) {
1009
                throw new Exception("You didn't specify requested inlinedataid"); }
1010

    
1011
            // check for permission
1012
            docId = MetaCatUtil
1013
                    .getDocIdWithoutRevFromInlineDataID(inlineDataId);
1014
            PermissionController controller = new PermissionController(docId);
1015
            // check top level read permission
1016
            if (!controller.hasPermission(user, groups,
1017
                    AccessControlInterface.READSTRING))
1018
            {
1019
                throw new Exception("User " + user
1020
                        + " doesn't have permission " + " to read document "
1021
                        + docId);
1022
            }
1023
            else
1024
            {
1025
              //check data access level
1026
              try
1027
              {
1028
                Hashtable unReadableInlineDataList =
1029
                    PermissionController.getUnReadableInlineDataIdList(docId,
1030
                    user, groups, false);
1031
                if (unReadableInlineDataList.containsValue(
1032
                          MetaCatUtil.getInlineDataIdWithoutRev(inlineDataId)))
1033
                {
1034
                  throw new Exception("User " + user
1035
                       + " doesn't have permission " + " to read inlinedata "
1036
                       + inlineDataId);
1037

    
1038
                }//if
1039
              }//try
1040
              catch (Exception e)
1041
              {
1042
                throw e;
1043
              }//catch
1044
            }//else
1045

    
1046
            // Get output stream
1047
            out = response.getOutputStream();
1048
            // read the inline data from the file
1049
            String inlinePath = MetaCatUtil.getOption("inlinedatafilepath");
1050
            File lineData = new File(inlinePath, inlineDataId);
1051
            FileInputStream input = new FileInputStream(lineData);
1052
            byte[] buffer = new byte[4 * 1024];
1053
            int bytes = input.read(buffer);
1054
            while (bytes != -1) {
1055
                out.write(buffer, 0, bytes);
1056
                bytes = input.read(buffer);
1057
            }
1058
            out.close();
1059

    
1060
            EventLog.getInstance().log(request.getRemoteAddr(), user,
1061
                    inlineDataId, "readinlinedata");
1062
        } catch (Exception e) {
1063
            try {
1064
                PrintWriter pw = null;
1065
                // Send error message back
1066
                if (out != null) {
1067
                    pw = new PrintWriter(out);
1068
                } else {
1069
                    pw = response.getWriter();
1070
                }
1071
                pw.println("<?xml version=\"1.0\"?>");
1072
                pw.println("<error>");
1073
                pw.println(e.getMessage());
1074
                pw.println("</error>");
1075
                // Close printwriter
1076
                pw.close();
1077
                // Close output stream if out is not null
1078
                if (out != null) {
1079
                    out.close();
1080
                }
1081
            } catch (IOException ioe) {
1082
                logMetacat.error("Problem with the servlet output "
1083
                        + "in MetacatServlet.handleExportAction: "
1084
                        + ioe.getMessage());
1085
            }
1086
            logMetacat.error(
1087
                    "Error in MetacatServlet.handleReadInlineDataAction: "
1088
                            + e.getMessage());
1089
        }
1090
    }
1091

    
1092
    /*
1093
     * Get the nodeid from xml_nodes for the inlinedataid
1094
     */
1095
    private long getInlineDataNodeId(String inLineDataId, String docId)
1096
            throws SQLException
1097
    {
1098
        long nodeId = 0;
1099
        String INLINE = "inline";
1100
        boolean hasRow;
1101
        PreparedStatement pStmt = null;
1102
        DBConnection conn = null;
1103
        int serialNumber = -1;
1104
        String sql = "SELECT nodeid FROM xml_nodes WHERE docid=? AND nodedata=? "
1105
                + "AND nodetype='TEXT' AND parentnodeid IN "
1106
                + "(SELECT nodeid FROM xml_nodes WHERE docid=? AND "
1107
                + "nodetype='ELEMENT' AND nodename='" + INLINE + "')";
1108

    
1109
        try {
1110
            //check out DBConnection
1111
            conn = DBConnectionPool
1112
                    .getDBConnection("AccessControlList.isAllowFirst");
1113
            serialNumber = conn.getCheckOutSerialNumber();
1114

    
1115
            pStmt = conn.prepareStatement(sql);
1116
            //bind value
1117
            pStmt.setString(1, docId);//docid
1118
            pStmt.setString(2, inLineDataId);//inlinedataid
1119
            pStmt.setString(3, docId);
1120
            // excute query
1121
            pStmt.execute();
1122
            ResultSet rs = pStmt.getResultSet();
1123
            hasRow = rs.next();
1124
            // get result
1125
            if (hasRow) {
1126
                nodeId = rs.getLong(1);
1127
            }//if
1128

    
1129
        } catch (SQLException e) {
1130
            throw e;
1131
        } finally {
1132
            try {
1133
                pStmt.close();
1134
            } finally {
1135
                DBConnectionPool.returnDBConnection(conn, serialNumber);
1136
            }
1137
        }
1138
        logMetacat.info("The nodeid for inlinedataid " + inLineDataId
1139
                + " is: " + nodeId);
1140
        return nodeId;
1141
    }
1142

    
1143
    /**
1144
     * Handle the "read" request of metadata/data files from Metacat or any
1145
     * files from Internet; transformed metadata XML document into HTML
1146
     * presentation if requested; zip files when more than one were requested.
1147
     *
1148
     * @param params the Hashtable of HTTP request parameters
1149
     * @param request the HTTP request object linked to the client
1150
     * @param response the HTTP response object linked to the client
1151
     * @param user the username sent the request
1152
     * @param groups the user's groupnames
1153
     */
1154
    private void handleReadAction(Hashtable params, HttpServletRequest request,
1155
            HttpServletResponse response, String user, String passWord,
1156
            String[] groups)
1157
    {
1158
        ServletOutputStream out = null;
1159
        ZipOutputStream zout = null;
1160
        PrintWriter pw = null;
1161
        boolean zip = false;
1162
        boolean withInlineData = true;
1163

    
1164
        try {
1165
            String[] docs = new String[0];
1166
            String docid = "";
1167
            String qformat = "";
1168
            String abstrpath = null;
1169

    
1170
            // read the params
1171
            if (params.containsKey("docid")) {
1172
                docs = (String[]) params.get("docid");
1173
            }
1174
            if (params.containsKey("qformat")) {
1175
                qformat = ((String[]) params.get("qformat"))[0];
1176
            }
1177
            // the param for only metadata (eml)
1178
            // we don't support read a eml document without inline data now.
1179
            /*if (params.containsKey("inlinedata")) {
1180

    
1181
                String inlineData = ((String[]) params.get("inlinedata"))[0];
1182
                if (inlineData.equalsIgnoreCase("false")) {
1183
                    withInlineData = false;
1184
                }
1185
            }*/
1186
            if ((docs.length > 1) || qformat.equals("zip")) {
1187
                zip = true;
1188
                out = response.getOutputStream();
1189
                response.setContentType("application/zip"); //MIME type
1190
                zout = new ZipOutputStream(out);
1191
            }
1192
            // go through the list of docs to read
1193
            for (int i = 0; i < docs.length; i++) {
1194
                try {
1195

    
1196
                    URL murl = new URL(docs[i]);
1197
                    Hashtable murlQueryStr = MetaCatUtil.parseQuery(
1198
                            murl.getQuery());
1199
                    // case docid="http://.../?docid=aaa"
1200
                    // or docid="metacat://.../?docid=bbb"
1201
                    if (murlQueryStr.containsKey("docid")) {
1202
                        // get only docid, eliminate the rest
1203
                        docid = (String) murlQueryStr.get("docid");
1204
                        if (zip) {
1205
                            addDocToZip(request, docid, zout, user, groups);
1206
                        } else {
1207
                            readFromMetacat(request, response, docid, qformat,
1208
                                    abstrpath, user, groups, zip, zout,
1209
                                    withInlineData, params);
1210
                        }
1211

    
1212
                        // case docid="http://.../filename"
1213
                    } else {
1214
                        docid = docs[i];
1215
                        if (zip) {
1216
                            addDocToZip(request, docid, zout, user, groups);
1217
                        } else {
1218
                            readFromURLConnection(response, docid);
1219
                        }
1220
                    }
1221

    
1222
                } catch (MalformedURLException mue) {
1223
                    docid = docs[i];
1224
                    if (zip) {
1225
                        addDocToZip(request, docid, zout, user, groups);
1226
                    } else {
1227
                        readFromMetacat(request, response, docid, qformat,
1228
                                abstrpath, user, groups, zip, zout,
1229
                                withInlineData, params);
1230
                    }
1231
                }
1232
            }
1233

    
1234
            if (zip) {
1235
                zout.finish(); //terminate the zip file
1236
                zout.close(); //close the zip stream
1237
            }
1238

    
1239
        } catch (McdbDocNotFoundException notFoundE) {
1240
            // To handle doc not found exception
1241
            // the docid which didn't be found
1242
            String notFoundDocId = notFoundE.getUnfoundDocId();
1243
            String notFoundRevision = notFoundE.getUnfoundRevision();
1244
            logMetacat.warn("Missed id: " + notFoundDocId);
1245
            logMetacat.warn("Missed rev: " + notFoundRevision);
1246
            try {
1247
                // read docid from remote server
1248
                readFromRemoteMetaCat(response, notFoundDocId,
1249
                        notFoundRevision, user, passWord, out, zip, zout);
1250
                // Close zout outputstream
1251
                if (zout != null) {
1252
                    zout.close();
1253
                }
1254
                // close output stream
1255
                if (out != null) {
1256
                    out.close();
1257
                }
1258

    
1259
            } catch (Exception exc) {
1260
                logMetacat.error(
1261
                        "Erorr in MetacatServlet.hanldReadAction: "
1262
                                + exc.getMessage());
1263
                try {
1264
                    if (out != null) {
1265
                        response.setContentType("text/xml");
1266
                        // Send back error message by printWriter
1267
                        pw = new PrintWriter(out);
1268
                        pw.println("<?xml version=\"1.0\"?>");
1269
                        pw.println("<error>");
1270
                        pw.println(notFoundE.getMessage());
1271
                        pw.println("</error>");
1272
                        pw.close();
1273
                        out.close();
1274

    
1275
                    } else {
1276
                        response.setContentType("text/xml"); //MIME type
1277
                        // Send back error message if out = null
1278
                        if (pw == null) {
1279
                            // If pw is null, open the respnose
1280
                            pw = response.getWriter();
1281
                        }
1282
                        pw.println("<?xml version=\"1.0\"?>");
1283
                        pw.println("<error>");
1284
                        pw.println(notFoundE.getMessage());
1285
                        pw.println("</error>");
1286
                        pw.close();
1287
                    }
1288
                    // close zout
1289
                    if (zout != null) {
1290
                        zout.close();
1291
                    }
1292
                } catch (IOException ie) {
1293
                    logMetacat.error("Problem with the servlet output "
1294
                            + "in MetacatServlet.handleReadAction: "
1295
                            + ie.getMessage());
1296
                }
1297
            }
1298
        } catch (Exception e) {
1299
            try {
1300

    
1301
                if (out != null) {
1302
                    response.setContentType("text/xml"); //MIME type
1303
                    pw = new PrintWriter(out);
1304
                    pw.println("<?xml version=\"1.0\"?>");
1305
                    pw.println("<error>");
1306
                    pw.println(e.getMessage());
1307
                    pw.println("</error>");
1308
                    pw.close();
1309
                    out.close();
1310
                } else {
1311
                    response.setContentType("text/xml"); //MIME type
1312
                    // Send back error message if out = null
1313
                    if (pw == null) {
1314
                        pw = response.getWriter();
1315
                    }
1316
                    pw.println("<?xml version=\"1.0\"?>");
1317
                    pw.println("<error>");
1318
                    pw.println(e.getMessage());
1319
                    pw.println("</error>");
1320
                    pw.close();
1321

    
1322
                }
1323
                // Close zip output stream
1324
                if (zout != null) {
1325
                    zout.close();
1326
                }
1327

    
1328
            } catch (IOException ioe) {
1329
                logMetacat.error("Problem with the servlet output "
1330
                        + "in MetacatServlet.handleReadAction: "
1331
                        + ioe.getMessage());
1332
                ioe.printStackTrace(System.out);
1333

    
1334
            }
1335

    
1336
            logMetacat.error(
1337
                    "Error in MetacatServlet.handleReadAction: "
1338
                            + e.getMessage());
1339
            //e.printStackTrace(System.out);
1340
        }
1341
    }
1342

    
1343
    /** read metadata or data from Metacat
1344
     */
1345
    private void readFromMetacat(HttpServletRequest request,
1346
            HttpServletResponse response, String docid, String qformat,
1347
            String abstrpath, String user, String[] groups, boolean zip,
1348
            ZipOutputStream zout, boolean withInlineData, Hashtable params)
1349
            throws ClassNotFoundException, IOException, SQLException,
1350
            McdbException, Exception
1351
    {
1352

    
1353
        try {
1354
            
1355
            // here is hack for handle docid=john.10(in order to tell mike.jim.10.1
1356
            // mike.jim.10, we require to provide entire docid with rev). But
1357
            // some old client they only provide docid without rev, so we need
1358
            // to handle this suituation. First we will check how many
1359
            // seperator here, if only one, we will append the rev in xml_documents
1360
            // to the id.
1361
            docid = appendRev(docid);
1362
         
1363
            DocumentImpl doc = new DocumentImpl(docid);
1364

    
1365
            //check the permission for read
1366
            if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1367
                Exception e = new Exception("User " + user
1368
                        + " does not have permission"
1369
                        + " to read the document with the docid " + docid);
1370

    
1371
                throw e;
1372
            }
1373

    
1374
            if (doc.getRootNodeID() == 0) {
1375
                // this is data file
1376
                String filepath = MetaCatUtil.getOption("datafilepath");
1377
                if (!filepath.endsWith("/")) {
1378
                    filepath += "/";
1379
                }
1380
                String filename = filepath + docid;
1381
                FileInputStream fin = null;
1382
                fin = new FileInputStream(filename);
1383

    
1384
                //MIME type
1385
                String contentType = getServletContext().getMimeType(filename);
1386
                if (contentType == null) {
1387
                    ContentTypeProvider provider = new ContentTypeProvider(
1388
                            docid);
1389
                    contentType = provider.getContentType();
1390
                    logMetacat.warn("Final contenttype is: "
1391
                            + contentType);
1392
                }
1393

    
1394
                response.setContentType(contentType);
1395
                // if we decide to use "application/octet-stream" for all data
1396
                // returns
1397
                // response.setContentType("application/octet-stream");
1398

    
1399
                try {
1400

    
1401
                    ServletOutputStream out = response.getOutputStream();
1402
                    byte[] buf = new byte[4 * 1024]; // 4K buffer
1403
                    int b = fin.read(buf);
1404
                    while (b != -1) {
1405
                        out.write(buf, 0, b);
1406
                        b = fin.read(buf);
1407
                    }
1408
                } finally {
1409
                    if (fin != null) fin.close();
1410
                }
1411

    
1412
            } else {
1413
                // this is metadata doc
1414
                if (qformat.equals("xml") || qformat.equals("")) {
1415
                    // if equals "", that means no qformat is specified. hence
1416
                    // by default the document should be returned in xml format
1417
                    // set content type first
1418
                    response.setContentType("text/xml"); //MIME type
1419
                    PrintWriter out = response.getWriter();
1420
                    doc.toXml(out, user, groups, withInlineData);
1421
                } else {
1422
                    response.setContentType("text/html"); //MIME type
1423
                    PrintWriter out = response.getWriter();
1424

    
1425
                    // Look up the document type
1426
                    String doctype = doc.getDoctype();
1427
                    // Transform the document to the new doctype
1428
                    DBTransform dbt = new DBTransform();
1429
                    dbt.transformXMLDocument(doc.toString(user, groups,
1430
                            withInlineData), doctype, "-//W3C//HTML//EN",
1431
                            qformat, out, params);
1432
                }
1433

    
1434
            }
1435
            EventLog.getInstance().log(request.getRemoteAddr(), user,
1436
                    docid, "read");
1437
        } catch (Exception except) {
1438
            throw except;
1439
        }
1440
    }
1441

    
1442
    /**
1443
     * read data from URLConnection
1444
     */
1445
    private void readFromURLConnection(HttpServletResponse response,
1446
            String docid) throws IOException, MalformedURLException
1447
    {
1448
        ServletOutputStream out = response.getOutputStream();
1449
        String contentType = getServletContext().getMimeType(docid); //MIME
1450
                                                                     // type
1451
        if (contentType == null) {
1452
            if (docid.endsWith(".xml")) {
1453
                contentType = "text/xml";
1454
            } else if (docid.endsWith(".css")) {
1455
                contentType = "text/css";
1456
            } else if (docid.endsWith(".dtd")) {
1457
                contentType = "text/plain";
1458
            } else if (docid.endsWith(".xsd")) {
1459
                contentType = "text/xml";
1460
            } else if (docid.endsWith("/")) {
1461
                contentType = "text/html";
1462
            } else {
1463
                File f = new File(docid);
1464
                if (f.isDirectory()) {
1465
                    contentType = "text/html";
1466
                } else {
1467
                    contentType = "application/octet-stream";
1468
                }
1469
            }
1470
        }
1471
        response.setContentType(contentType);
1472
        // if we decide to use "application/octet-stream" for all data returns
1473
        // response.setContentType("application/octet-stream");
1474

    
1475
        // this is http url
1476
        URL url = new URL(docid);
1477
        BufferedInputStream bis = null;
1478
        try {
1479
            bis = new BufferedInputStream(url.openStream());
1480
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1481
            int b = bis.read(buf);
1482
            while (b != -1) {
1483
                out.write(buf, 0, b);
1484
                b = bis.read(buf);
1485
            }
1486
        } finally {
1487
            if (bis != null) bis.close();
1488
        }
1489

    
1490
    }
1491

    
1492
    /**
1493
     * read file/doc and write to ZipOutputStream
1494
     *
1495
     * @param docid
1496
     * @param zout
1497
     * @param user
1498
     * @param groups
1499
     * @throws ClassNotFoundException
1500
     * @throws IOException
1501
     * @throws SQLException
1502
     * @throws McdbException
1503
     * @throws Exception
1504
     */
1505
    private void addDocToZip(HttpServletRequest request, String docid,
1506
            ZipOutputStream zout, String user, String[] groups) throws
1507
            ClassNotFoundException, IOException, SQLException, McdbException,
1508
            Exception
1509
    {
1510
        byte[] bytestring = null;
1511
        ZipEntry zentry = null;
1512

    
1513
        try {
1514
            URL url = new URL(docid);
1515

    
1516
            // this http url; read from URLConnection; add to zip
1517
            zentry = new ZipEntry(docid);
1518
            zout.putNextEntry(zentry);
1519
            BufferedInputStream bis = null;
1520
            try {
1521
                bis = new BufferedInputStream(url.openStream());
1522
                byte[] buf = new byte[4 * 1024]; // 4K buffer
1523
                int b = bis.read(buf);
1524
                while (b != -1) {
1525
                    zout.write(buf, 0, b);
1526
                    b = bis.read(buf);
1527
                }
1528
            } finally {
1529
                if (bis != null) bis.close();
1530
            }
1531
            zout.closeEntry();
1532

    
1533
        } catch (MalformedURLException mue) {
1534

    
1535
            // this is metacat doc (data file or metadata doc)
1536
            try {
1537
                DocumentImpl doc = new DocumentImpl(docid);
1538

    
1539
                //check the permission for read
1540
                if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1541
                    Exception e = new Exception("User " + user
1542
                            + " does not have "
1543
                            + "permission to read the document with the docid "
1544
                            + docid);
1545
                    throw e;
1546
                }
1547

    
1548
                if (doc.getRootNodeID() == 0) {
1549
                    // this is data file; add file to zip
1550
                    String filepath = MetaCatUtil.getOption("datafilepath");
1551
                    if (!filepath.endsWith("/")) {
1552
                        filepath += "/";
1553
                    }
1554
                    String filename = filepath + docid;
1555
                    FileInputStream fin = null;
1556
                    fin = new FileInputStream(filename);
1557
                    try {
1558

    
1559
                        zentry = new ZipEntry(docid);
1560
                        zout.putNextEntry(zentry);
1561
                        byte[] buf = new byte[4 * 1024]; // 4K buffer
1562
                        int b = fin.read(buf);
1563
                        while (b != -1) {
1564
                            zout.write(buf, 0, b);
1565
                            b = fin.read(buf);
1566
                        }
1567
                    } finally {
1568
                        if (fin != null) fin.close();
1569
                    }
1570
                    zout.closeEntry();
1571

    
1572
                } else {
1573
                    // this is metadata doc; add doc to zip
1574
                    bytestring = doc.toString().getBytes();
1575
                    zentry = new ZipEntry(docid + ".xml");
1576
                    zentry.setSize(bytestring.length);
1577
                    zout.putNextEntry(zentry);
1578
                    zout.write(bytestring, 0, bytestring.length);
1579
                    zout.closeEntry();
1580
                }
1581
                EventLog.getInstance().log(request.getRemoteAddr(), user,
1582
                        docid, "read");
1583
            } catch (Exception except) {
1584
                throw except;
1585
            }
1586
        }
1587
    }
1588

    
1589
    /**
1590
     * If metacat couldn't find a data file or document locally, it will read
1591
     * this docid from its home server. This is for the replication feature
1592
     */
1593
    private void readFromRemoteMetaCat(HttpServletResponse response,
1594
            String docid, String rev, String user, String password,
1595
            ServletOutputStream out, boolean zip, ZipOutputStream zout)
1596
            throws Exception
1597
    {
1598
        // Create a object of RemoteDocument, "" is for zipEntryPath
1599
        RemoteDocument remoteDoc = new RemoteDocument(docid, rev, user,
1600
                password, "");
1601
        String docType = remoteDoc.getDocType();
1602
        // Only read data file
1603
        if (docType.equals("BIN")) {
1604
            // If it is zip format
1605
            if (zip) {
1606
                remoteDoc.readDocumentFromRemoteServerByZip(zout);
1607
            } else {
1608
                if (out == null) {
1609
                    out = response.getOutputStream();
1610
                }
1611
                response.setContentType("application/octet-stream");
1612
                remoteDoc.readDocumentFromRemoteServer(out);
1613
            }
1614
        } else {
1615
            throw new Exception("Docid: " + docid + "." + rev
1616
                    + " couldn't find");
1617
        }
1618
    }
1619

    
1620
    /**
1621
     * Handle the database putdocument request and write an XML document to the
1622
     * database connection
1623
     */
1624
    private void handleInsertOrUpdateAction(HttpServletRequest request,
1625
            HttpServletResponse response, PrintWriter out, Hashtable params,
1626
            String user, String[] groups)
1627
    {
1628
        DBConnection dbConn = null;
1629
        int serialNumber = -1;
1630

    
1631
        if(params.get("docid") == null){
1632
            out.println("<?xml version=\"1.0\"?>");
1633
            out.println("<error>");
1634
            out.println("Docid not specified");
1635
            out.println("</error>");
1636
            logMetacat.error("Docid not specified");
1637
            return;
1638
        }
1639
        
1640
        if(!MetaCatUtil.canInsertOrUpdate(user, groups)){
1641
        	out.println("<?xml version=\"1.0\"?>");
1642
            out.println("<error>");
1643
            out.println("User '" + user + "' not allowed to insert and update");
1644
            out.println("</error>");
1645
            logMetacat.error("User '" + user + "' not allowed to insert and update");
1646
            return;
1647
        }
1648

    
1649
        try {
1650
            // Get the document indicated
1651
            String[] doctext = (String[]) params.get("doctext");
1652
            String pub = null;
1653
            if (params.containsKey("public")) {
1654
                pub = ((String[]) params.get("public"))[0];
1655
            }
1656

    
1657
            StringReader dtd = null;
1658
            if (params.containsKey("dtdtext")) {
1659
                String[] dtdtext = (String[]) params.get("dtdtext");
1660
                try {
1661
                    if (!dtdtext[0].equals("")) {
1662
                        dtd = new StringReader(dtdtext[0]);
1663
                    }
1664
                } catch (NullPointerException npe) {
1665
                }
1666
            }
1667

    
1668
            if(doctext == null){
1669
                out.println("<?xml version=\"1.0\"?>");
1670
                out.println("<error>");
1671
                out.println("Document text not submitted");
1672
                out.println("</error>");
1673
                return;
1674
            }
1675

    
1676
            StringReader xml = new StringReader(doctext[0]);
1677
            boolean validate = false;
1678
            DocumentImplWrapper documentWrapper = null;
1679
            try {
1680
                // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ...
1681
                // >
1682
                // in order to decide whether to use validation parser
1683
                validate = needDTDValidation(xml);
1684
                if (validate) {
1685
                    // set a dtd base validation parser
1686
                    String rule = DocumentImpl.DTD;
1687
                    documentWrapper = new DocumentImplWrapper(rule, validate);
1688
                } else {
1689

    
1690
                    String namespace = findNamespace(xml);
1691
                    
1692
                	if (namespace != null) {
1693
                		if (namespace.compareTo(DocumentImpl.EML2_0_0NAMESPACE) == 0
1694
                				|| namespace.compareTo(
1695
                				DocumentImpl.EML2_0_1NAMESPACE) == 0) {
1696
                			// set eml2 base	 validation parser
1697
                			String rule = DocumentImpl.EML200;
1698
                			// using emlparser to check id validation
1699
                			EMLParser parser = new EMLParser(doctext[0]);
1700
                			documentWrapper = new DocumentImplWrapper(rule, true);
1701
                		} else if (namespace.compareTo(
1702
                                DocumentImpl.EML2_1_0NAMESPACE) == 0) {
1703
                			// set eml2 base validation parser
1704
                			String rule = DocumentImpl.EML210;
1705
                			// using emlparser to check id validation
1706
                			EMLParser parser = new EMLParser(doctext[0]);
1707
                			documentWrapper = new DocumentImplWrapper(rule, true);
1708
                		} else {
1709
                			// set schema base validation parser
1710
                			String rule = DocumentImpl.SCHEMA;
1711
                			documentWrapper = new DocumentImplWrapper(rule, true);
1712
                		}
1713
                	} else {
1714
                		documentWrapper = new DocumentImplWrapper("", false);
1715
                	}
1716
                }
1717

    
1718
                String[] action = (String[]) params.get("action");
1719
                String[] docid = (String[]) params.get("docid");
1720
                String newdocid = null;
1721

    
1722
                String doAction = null;
1723
                if (action[0].equals("insert")) {
1724
                    doAction = "INSERT";
1725
                } else if (action[0].equals("update")) {
1726
                    doAction = "UPDATE";
1727
                }
1728

    
1729
                try {
1730
                    // get a connection from the pool
1731
                    dbConn = DBConnectionPool
1732
                            .getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1733
                    serialNumber = dbConn.getCheckOutSerialNumber();
1734

    
1735
                    // write the document to the database
1736
                    try {
1737
                        String accNumber = docid[0];
1738
                        logMetacat.warn("" + doAction + " "
1739
                                + accNumber + "...");
1740
                        if (accNumber.equals("")) {
1741
                            accNumber = null;
1742
                        }
1743
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1744
                                doAction, accNumber, user, groups);
1745
                        EventLog.getInstance().log(request.getRemoteAddr(),
1746
                                user, accNumber, action[0]);
1747
                    } catch (NullPointerException npe) {
1748
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1749
                                doAction, null, user, groups);
1750
                        EventLog.getInstance().log(request.getRemoteAddr(),
1751
                                user, "", action[0]);
1752
                    }
1753
                }
1754
                finally {
1755
                    // Return db connection
1756
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1757
                }
1758

    
1759
                // set content type and other response header fields first
1760
                //response.setContentType("text/xml");
1761
                out.println("<?xml version=\"1.0\"?>");
1762
                out.println("<success>");
1763
                out.println("<docid>" + newdocid + "</docid>");
1764
                out.println("</success>");
1765

    
1766
            } catch (NullPointerException npe) {
1767
                //response.setContentType("text/xml");
1768
                out.println("<?xml version=\"1.0\"?>");
1769
                out.println("<error>");
1770
                out.println(npe.getMessage());
1771
                out.println("</error>");
1772
                logMetacat.warn("Error in writing eml document to the database" + npe.getMessage());
1773
                npe.printStackTrace();
1774
            }
1775
        } catch (Exception e) {
1776
            //response.setContentType("text/xml");
1777
            out.println("<?xml version=\"1.0\"?>");
1778
            out.println("<error>");
1779
            out.println(e.getMessage());
1780
            out.println("</error>");
1781
            logMetacat.warn("Error in writing eml document to the database" + e.getMessage());
1782
            e.printStackTrace();
1783
        }
1784
    }
1785

    
1786
    /**
1787
     * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > in
1788
     * order to decide whether to use validation parser
1789
     */
1790
    private static boolean needDTDValidation(StringReader xmlreader)
1791
            throws IOException
1792
    {
1793

    
1794
        StringBuffer cbuff = new StringBuffer();
1795
        java.util.Stack st = new java.util.Stack();
1796
        boolean validate = false;
1797
        int c;
1798
        int inx;
1799

    
1800
        // read from the stream until find the keywords
1801
        while ((st.empty() || st.size() < 4) && ((c = xmlreader.read()) != -1)) {
1802
            cbuff.append((char) c);
1803

    
1804
            // "<!DOCTYPE" keyword is found; put it in the stack
1805
            if ((inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1) {
1806
                cbuff = new StringBuffer();
1807
                st.push("<!DOCTYPE");
1808
            }
1809
            // "PUBLIC" keyword is found; put it in the stack
1810
            if ((inx = cbuff.toString().indexOf("PUBLIC")) != -1) {
1811
                cbuff = new StringBuffer();
1812
                st.push("PUBLIC");
1813
            }
1814
            // "SYSTEM" keyword is found; put it in the stack
1815
            if ((inx = cbuff.toString().indexOf("SYSTEM")) != -1) {
1816
                cbuff = new StringBuffer();
1817
                st.push("SYSTEM");
1818
            }
1819
            // ">" character is found; put it in the stack
1820
            // ">" is found twice: fisrt from <?xml ...?>
1821
            // and second from <!DOCTYPE ... >
1822
            if ((inx = cbuff.toString().indexOf(">")) != -1) {
1823
                cbuff = new StringBuffer();
1824
                st.push(">");
1825
            }
1826
        }
1827

    
1828
        // close the stream
1829
        xmlreader.reset();
1830

    
1831
        // check the stack whether it contains the keywords:
1832
        // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1833
        if (st.size() == 4) {
1834
            if (((String) st.pop()).equals(">")
1835
                    && (((String) st.peek()).equals("PUBLIC") | ((String) st
1836
                            .pop()).equals("SYSTEM"))
1837
                    && ((String) st.pop()).equals("<!DOCTYPE")) {
1838
                validate = true;
1839
            }
1840
        }
1841

    
1842
        logMetacat.warn("Validation for dtd is " + validate);
1843
        return validate;
1844
    }
1845

    
1846
    // END OF INSERT/UPDATE SECTION
1847

    
1848
    /* check if the xml string contains key words to specify schema loocation */
1849
    private String findNamespace(StringReader xml) throws IOException
1850
    {
1851
        String namespace = null;
1852

    
1853
        String eml2_0_0NameSpace = DocumentImpl.EML2_0_0NAMESPACE;
1854
        String eml2_0_1NameSpace = DocumentImpl.EML2_0_1NAMESPACE;
1855
        String eml2_1_0NameSpace = DocumentImpl.EML2_1_0NAMESPACE;
1856

    
1857
        if (xml == null) {
1858
            logMetacat.warn("Validation for schema is "
1859
                    + namespace);
1860
            return namespace;
1861
        }
1862
        String targetLine = getSchemaLine(xml);
1863

    
1864
        if (targetLine != null) {
1865

    
1866
        	// find if the root element has prefix
1867
        	String prefix = getPrefix(targetLine);
1868
        	logMetacat.info("prefix is:" + prefix);
1869
        	int startIndex = 0;
1870
        	
1871
        	
1872
        	if(prefix != null)
1873
        	{
1874
        		// if prefix found then look for xmlns:prefix
1875
        		// element to find the ns 
1876
        		String namespaceWithPrefix = NAMESPACEKEYWORD 
1877
        					+ ":" + prefix;
1878
        		startIndex = targetLine.indexOf(namespaceWithPrefix);
1879
            	logMetacat.info("namespaceWithPrefix is:" + namespaceWithPrefix+":");
1880
            	logMetacat.info("startIndex is:" + startIndex);
1881
        		
1882
        	} else {
1883
        		// if prefix not found then look for xmlns
1884
        		// attribute to find the ns 
1885
        		startIndex = targetLine.indexOf(NAMESPACEKEYWORD);
1886
            	logMetacat.info("startIndex is:" + startIndex);
1887
        	}
1888
        		
1889
            int start = 1;
1890
            int end = 1;
1891
            String namespaceString = null;
1892
            int count = 0;
1893
            if (startIndex != -1) {
1894
                for (int i = startIndex; i < targetLine.length(); i++) {
1895
                    if (targetLine.charAt(i) == '"') {
1896
                        count++;
1897
                    }
1898
                    if (targetLine.charAt(i) == '"' && count == 1) {
1899
                        start = i;
1900
                    }
1901
                    if (targetLine.charAt(i) == '"' && count == 2) {
1902
                        end = i;
1903
                        break;
1904
                    }
1905
                }
1906
            } 
1907
            // else: xmlns not found. namespace = null will be returned
1908

    
1909
         	logMetacat.info("targetLine is " + targetLine);
1910
         	logMetacat.debug("start is " + end);
1911
         	logMetacat.debug("end is " + end);
1912
           
1913
            if(start < end){
1914
            	namespaceString = targetLine.substring(start + 1, end);
1915
            	logMetacat.info("namespaceString is " + namespaceString);
1916
            }
1917
            logMetacat.info("namespace in xml is: "
1918
                    + namespaceString);
1919
            if(namespaceString != null){
1920
            	if (namespaceString.indexOf(eml2_0_0NameSpace) != -1) {
1921
            		namespace = eml2_0_0NameSpace;
1922
            	} else if (namespaceString.indexOf(eml2_0_1NameSpace) != -1) {
1923
            		namespace = eml2_0_1NameSpace;
1924
            	} else if (namespaceString.indexOf(eml2_1_0NameSpace) != -1) {
1925
            		namespace = eml2_1_0NameSpace;
1926
            	} else {
1927
            		namespace = namespaceString;
1928
            	}
1929
            }
1930
        }
1931

    
1932
        logMetacat.warn("Validation for eml is " + namespace);
1933

    
1934
        return namespace;
1935

    
1936
    }
1937

    
1938
    private String getSchemaLine(StringReader xml) throws IOException
1939
    {
1940
        // find the line
1941
        String secondLine = null;
1942
        int count = 0;
1943
        int endIndex = 0;
1944
        int startIndex = 0;
1945
        final int TARGETNUM = 2;
1946
        StringBuffer buffer = new StringBuffer();
1947
        boolean comment = false;
1948
        char thirdPreviousCharacter = '?';
1949
        char secondPreviousCharacter = '?';
1950
        char previousCharacter = '?';
1951
        char currentCharacter = '?';
1952
        int tmp = xml.read();
1953
        while (tmp != -1) {
1954
            currentCharacter = (char)tmp;
1955
            //in a comment
1956
            if (currentCharacter == '-' && previousCharacter == '-'
1957
                    && secondPreviousCharacter == '!'
1958
                    && thirdPreviousCharacter == '<') {
1959
                comment = true;
1960
            }
1961
            //out of comment
1962
            if (comment && currentCharacter == '>' && previousCharacter == '-'
1963
                    && secondPreviousCharacter == '-') {
1964
                comment = false;
1965
            }
1966

    
1967
            //this is not comment
1968
            if (currentCharacter != '!' && previousCharacter == '<' && !comment) {
1969
                count++;
1970
            }
1971
            // get target line
1972
            if (count == TARGETNUM && currentCharacter != '>') {
1973
                buffer.append(currentCharacter);
1974
            }
1975
            if (count == TARGETNUM && currentCharacter == '>') {
1976
                break;
1977
            }
1978
            thirdPreviousCharacter = secondPreviousCharacter;
1979
            secondPreviousCharacter = previousCharacter;
1980
            previousCharacter = currentCharacter;
1981
            tmp = xml.read();
1982
        }
1983
        secondLine = buffer.toString();
1984
        logMetacat.info("the second line string is: " + secondLine);
1985
        
1986
        xml.reset();
1987
        return secondLine;
1988
    }
1989

    
1990
    private String getPrefix(String schemaLine)
1991
    {
1992
    	String prefix = null;
1993
    	String rootElement = schemaLine.substring(0, schemaLine.indexOf(" "));
1994
        logMetacat.info("rootElement:" + rootElement);
1995
        
1996
        if(rootElement.indexOf(":") > 0){
1997
        	prefix = rootElement.substring(rootElement.indexOf(":") + 1,
1998
        			rootElement.length());
1999
        } 
2000
        return prefix.trim();
2001
    }
2002

    
2003
    /**
2004
     * Handle the database delete request and delete an XML document from the
2005
     * database connection
2006
     */
2007
    private void handleDeleteAction(PrintWriter out, Hashtable params,
2008
            HttpServletRequest request, HttpServletResponse response,
2009
            String user, String[] groups)
2010
    {
2011

    
2012
        String[] docid = (String[]) params.get("docid");
2013

    
2014
        if(docid == null){
2015
          response.setContentType("text/xml");
2016
          out.println("<?xml version=\"1.0\"?>");
2017
          out.println("<error>");
2018
          out.println("Docid not specified.");
2019
          out.println("</error>");
2020
          logMetacat.error("Docid not specified for the document to be deleted.");
2021
        } else {
2022

    
2023
            // delete the document from the database
2024
            try {
2025

    
2026
                try {
2027
                    // null means notify server is null
2028
                    DocumentImpl.delete(docid[0], user, groups, null);
2029
                    EventLog.getInstance().log(request.getRemoteAddr(),
2030
                                               user, docid[0], "delete");
2031
                    response.setContentType("text/xml");
2032
                    out.println("<?xml version=\"1.0\"?>");
2033
                    out.println("<success>");
2034
                    out.println("Document deleted.");
2035
                    out.println("</success>");
2036
                    logMetacat.warn("Document deleted.");
2037
                }
2038
                catch (AccessionNumberException ane) {
2039
                    response.setContentType("text/xml");
2040
                    out.println("<?xml version=\"1.0\"?>");
2041
                    out.println("<error>");
2042
                    //out.println("Error deleting document!!!");
2043
                    out.println(ane.getMessage());
2044
                    out.println("</error>");
2045
                    logMetacat.error("Document could not be deleted: " 
2046
                    		+ ane.getMessage());
2047
                }
2048
            }
2049
            catch (Exception e) {
2050
                response.setContentType("text/xml");
2051
                out.println("<?xml version=\"1.0\"?>");
2052
                out.println("<error>");
2053
                out.println(e.getMessage());
2054
                out.println("</error>");
2055
                logMetacat.error("Document could not be deleted: " 
2056
                		+ e.getMessage());
2057
            }
2058
        }
2059
    }
2060

    
2061
    /**
2062
     * Handle the validation request and return the results to the requestor
2063
     */
2064
    private void handleValidateAction(PrintWriter out, Hashtable params)
2065
    {
2066

    
2067
        // Get the document indicated
2068
        String valtext = null;
2069
        DBConnection dbConn = null;
2070
        int serialNumber = -1;
2071

    
2072
        try {
2073
            valtext = ((String[]) params.get("valtext"))[0];
2074
        } catch (Exception nullpe) {
2075

    
2076
            String docid = null;
2077
            try {
2078
                // Find the document id number
2079
                docid = ((String[]) params.get("docid"))[0];
2080

    
2081
                // Get the document indicated from the db
2082
                DocumentImpl xmldoc = new DocumentImpl(docid);
2083
                valtext = xmldoc.toString();
2084

    
2085
            } catch (NullPointerException npe) {
2086

    
2087
                out.println("<error>Error getting document ID: " + docid
2088
                        + "</error>");
2089
                //if ( conn != null ) { util.returnConnection(conn); }
2090
                return;
2091
            } catch (Exception e) {
2092

    
2093
                out.println(e.getMessage());
2094
            }
2095
        }
2096

    
2097
        try {
2098
            // get a connection from the pool
2099
            dbConn = DBConnectionPool
2100
                    .getDBConnection("MetaCatServlet.handleValidateAction");
2101
            serialNumber = dbConn.getCheckOutSerialNumber();
2102
            DBValidate valobj = new DBValidate(dbConn);
2103
            boolean valid = valobj.validateString(valtext);
2104

    
2105
            // set content type and other response header fields first
2106

    
2107
            out.println(valobj.returnErrors());
2108

    
2109
        } catch (NullPointerException npe2) {
2110
            // set content type and other response header fields first
2111

    
2112
            out.println("<error>Error validating document.</error>");
2113
        } catch (Exception e) {
2114

    
2115
            out.println(e.getMessage());
2116
        } finally {
2117
            // Return db connection
2118
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2119
        }
2120
    }
2121

    
2122
    /**
2123
     * Handle "getrevsionanddoctype" action Given a docid, return it's current
2124
     * revision and doctype from data base The output is String look like
2125
     * "rev;doctype"
2126
     */
2127
    private void handleGetRevisionAndDocTypeAction(PrintWriter out,
2128
            Hashtable params)
2129
    {
2130
        // To store doc parameter
2131
        String[] docs = new String[10];
2132
        // Store a single doc id
2133
        String givenDocId = null;
2134
        // Get docid from parameters
2135
        if (params.containsKey("docid")) {
2136
            docs = (String[]) params.get("docid");
2137
        }
2138
        // Get first docid form string array
2139
        givenDocId = docs[0];
2140

    
2141
        try {
2142
            // Make sure there is a docid
2143
            if (givenDocId == null || givenDocId.equals("")) { throw new Exception(
2144
                    "User didn't specify docid!"); }//if
2145

    
2146
            // Create a DBUtil object
2147
            DBUtil dbutil = new DBUtil();
2148
            // Get a rev and doctype
2149
            String revAndDocType = dbutil
2150
                    .getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
2151
            out.println(revAndDocType);
2152

    
2153
        } catch (Exception e) {
2154
            // Handle exception
2155
            out.println("<?xml version=\"1.0\"?>");
2156
            out.println("<error>");
2157
            out.println(e.getMessage());
2158
            out.println("</error>");
2159
        }
2160

    
2161
    }
2162

    
2163
    /**
2164
     * Handle "getaccesscontrol" action. Read Access Control List from db
2165
     * connection in XML format
2166
     */
2167
    private void handleGetAccessControlAction(PrintWriter out,
2168
            Hashtable params, HttpServletResponse response, String username,
2169
            String[] groupnames)
2170
    {
2171
        DBConnection dbConn = null;
2172
        int serialNumber = -1;
2173
        String docid = ((String[]) params.get("docid"))[0];
2174

    
2175
        try {
2176

    
2177
            // get connection from the pool
2178
            dbConn = DBConnectionPool
2179
                    .getDBConnection("MetaCatServlet.handleGetAccessControlAction");
2180
            serialNumber = dbConn.getCheckOutSerialNumber();
2181
            AccessControlList aclobj = new AccessControlList(dbConn);
2182
            String acltext = aclobj.getACL(docid, username, groupnames);
2183
            out.println(acltext);
2184

    
2185
        } catch (Exception e) {
2186
            out.println("<?xml version=\"1.0\"?>");
2187
            out.println("<error>");
2188
            out.println(e.getMessage());
2189
            out.println("</error>");
2190
        } finally {
2191
            // Retrun db connection to pool
2192
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2193
        }
2194
    }
2195

    
2196
    /**
2197
     * Handle the "getprincipals" action. Read all principals from
2198
     * authentication scheme in XML format
2199
     */
2200
    private void handleGetPrincipalsAction(PrintWriter out, String user,
2201
            String password)
2202
    {
2203
        try {
2204
            AuthSession auth = new AuthSession();
2205
            String principals = auth.getPrincipals(user, password);
2206
            out.println(principals);
2207

    
2208
        } catch (Exception e) {
2209
            out.println("<?xml version=\"1.0\"?>");
2210
            out.println("<error>");
2211
            out.println(e.getMessage());
2212
            out.println("</error>");
2213
        }
2214
    }
2215

    
2216
    /**
2217
     * Handle "getdoctypes" action. Read all doctypes from db connection in XML
2218
     * format
2219
     */
2220
    private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
2221
            HttpServletResponse response)
2222
    {
2223
        try {
2224
            DBUtil dbutil = new DBUtil();
2225
            String doctypes = dbutil.readDoctypes();
2226
            out.println(doctypes);
2227
        } catch (Exception e) {
2228
            out.println("<?xml version=\"1.0\"?>");
2229
            out.println("<error>");
2230
            out.println(e.getMessage());
2231
            out.println("</error>");
2232
        }
2233
    }
2234

    
2235
    /**
2236
     * Handle the "getdtdschema" action. Read DTD or Schema file for a given
2237
     * doctype from Metacat catalog system
2238
     */
2239
    private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
2240
            HttpServletResponse response)
2241
    {
2242

    
2243
        String doctype = null;
2244
        String[] doctypeArr = (String[]) params.get("doctype");
2245

    
2246
        // get only the first doctype specified in the list of doctypes
2247
        // it could be done for all doctypes in that list
2248
        if (doctypeArr != null) {
2249
            doctype = ((String[]) params.get("doctype"))[0];
2250
        }
2251

    
2252
        try {
2253
            DBUtil dbutil = new DBUtil();
2254
            String dtdschema = dbutil.readDTDSchema(doctype);
2255
            out.println(dtdschema);
2256

    
2257
        } catch (Exception e) {
2258
            out.println("<?xml version=\"1.0\"?>");
2259
            out.println("<error>");
2260
            out.println(e.getMessage());
2261
            out.println("</error>");
2262
        }
2263

    
2264
    }
2265

    
2266
    /**
2267
     * Handle the "getlastdocid" action. Get the latest docid with rev number
2268
     * from db connection in XML format
2269
     */
2270
    private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
2271
            HttpServletResponse response)
2272
    {
2273

    
2274
        String scope = ((String[]) params.get("scope"))[0];
2275
        if (scope == null) {
2276
            scope = ((String[]) params.get("username"))[0];
2277
        }
2278

    
2279
        try {
2280

    
2281
            DBUtil dbutil = new DBUtil();
2282
            String lastDocid = dbutil.getMaxDocid(scope);
2283
            out.println("<?xml version=\"1.0\"?>");
2284
            out.println("<lastDocid>");
2285
            out.println("  <scope>" + scope + "</scope>");
2286
            out.println("  <docid>" + lastDocid + "</docid>");
2287
            out.println("</lastDocid>");
2288

    
2289
        } catch (Exception e) {
2290
            out.println("<?xml version=\"1.0\"?>");
2291
            out.println("<error>");
2292
            out.println(e.getMessage());
2293
            out.println("</error>");
2294
        }
2295
    }
2296

    
2297
    /**
2298
     * Print a report from the event log based on filter parameters passed in
2299
     * from the web.
2300
     *
2301
     * @param params the parameters from the web request
2302
     * @param request the http request object for getting request details
2303
     * @param response the http response object for writing output
2304
     */
2305
    private void handleGetLogAction(Hashtable params, HttpServletRequest request,
2306
            HttpServletResponse response, String username, String[] groups)
2307
    {
2308
        try {
2309
            response.setContentType("text/xml");
2310
            PrintWriter out = response.getWriter();
2311

    
2312
            // Check that the user is authenticated as an administrator account
2313
            if (!MetaCatUtil.isAdministrator(username, groups)) {
2314
                out.print("<error>");
2315
                out.print("The user \"" + username +
2316
                        "\" is not authorized for this action.");
2317
                out.print("</error>");
2318
                return;
2319
            }
2320

    
2321
            // Get all of the parameters in the correct formats
2322
            String[] ipAddress = (String[])params.get("ipaddress");
2323
            String[] principal = (String[])params.get("principal");
2324
            String[] docid = (String[])params.get("docid");
2325
            String[] event = (String[])params.get("event");
2326
            String[] startArray = (String[]) params.get("start");
2327
            String[] endArray = (String[]) params.get("end");
2328
            String start = null;
2329
            String end = null;
2330
            if (startArray != null) {
2331
                start = startArray[0];
2332
            }
2333
            if (endArray != null) {
2334
                end = endArray[0];
2335
            }
2336
            Timestamp startDate = null;
2337
            Timestamp endDate = null;
2338
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
2339
            try {
2340
                if (start != null) {
2341
                    startDate = new Timestamp((format.parse(start)).getTime());
2342
                }
2343
                if (end != null) {
2344
                    endDate = new Timestamp((format.parse(end)).getTime());
2345
                }
2346
            } catch (ParseException e) {
2347
                System.out.println("Failed to created Timestamp from input.");
2348
            }
2349

    
2350
            // Request the report by passing the filter parameters
2351
            out.println(EventLog.getInstance().getReport(ipAddress, principal,
2352
                    docid, event, startDate, endDate));
2353
            out.close();
2354
        } catch (IOException e) {
2355
            logMetacat.error(
2356
                    "Could not open http response for writing: " + e.getMessage());
2357
        }
2358
    }
2359

    
2360
    /**
2361
     * Rebuild the index for one or more documents. If the docid parameter is
2362
     * provided, rebuild for just that one document or list of documents. If
2363
     * not, then rebuild the index for all documents in the xml_documents
2364
     * table.
2365
     *
2366
     * @param params the parameters from the web request
2367
     * @param request the http request object for getting request details
2368
     * @param response the http response object for writing output
2369
     * @param username the username of the authenticated user
2370
     */
2371
    private void handleBuildIndexAction(Hashtable params,
2372
            HttpServletRequest request, HttpServletResponse response,
2373
            String username, String[] groups)
2374
    {
2375
        // Get all of the parameters in the correct formats
2376
        String[] docid = (String[])params.get("docid");
2377

    
2378
        // Rebuild the indices for appropriate documents
2379
        try {
2380
            response.setContentType("text/xml");
2381
            PrintWriter out = response.getWriter();
2382

    
2383
            // Check that the user is authenticated as an administrator account
2384
            if (!MetaCatUtil.isAdministrator(username, groups)) {
2385
                out.print("<error>");
2386
                out.print("The user \"" + username +
2387
                        "\" is not authorized for this action.");
2388
                out.print("</error>");
2389
                return;
2390
            }
2391

    
2392
            // Process the documents
2393
            out.println("<success>");
2394
            if (docid == null || docid.length == 0) {
2395
                // Process all of the documents
2396
                try {
2397
                    Vector documents = getDocumentList();
2398
                    Iterator it = documents.iterator();
2399
                    while (it.hasNext()) {
2400
                        String id = (String) it.next();
2401
                        buildDocumentIndex(id, out);
2402
                    }
2403
                } catch (SQLException se) {
2404
                    out.print("<error>");
2405
                    out.print(se.getMessage());
2406
                    out.println("</error>");
2407
                }
2408
            } else {
2409
                // Only process the requested documents
2410
                for (int i = 0; i < docid.length; i++) {
2411
                    buildDocumentIndex(docid[i], out);
2412
                }
2413
            }
2414
            out.println("</success>");
2415
            out.close();
2416
        } catch (IOException e) {
2417
            logMetacat.error(
2418
                    "Could not open http response for writing: "
2419
                    + e.getMessage());
2420
        }
2421
    }
2422

    
2423
    /**
2424
     * Build the index for one document by reading the document and
2425
     * calling its buildIndex() method.
2426
     *
2427
     * @param docid the document (with revision) to rebuild
2428
     * @param out the PrintWriter to which output is printed
2429
     */
2430
    private void buildDocumentIndex(String docid, PrintWriter out)
2431
    {
2432
        try {
2433
            DocumentImpl doc = new DocumentImpl(docid, false);
2434
            doc.buildIndex();
2435
            out.print("<docid>" + docid);
2436
            out.println("</docid>");
2437
        } catch (McdbException me) {
2438
            out.print("<error>");
2439
            out.print(me.getMessage());
2440
            out.println("</error>");
2441
        }
2442
    }
2443

    
2444
    /**
2445
     * Handle documents passed to metacat that are encoded using the
2446
     * "multipart/form-data" mime type. This is typically used for uploading
2447
     * data files which may be binary and large.
2448
     */
2449
    private void handleMultipartForm(HttpServletRequest request,
2450
            HttpServletResponse response)
2451
    {
2452
        PrintWriter out = null;
2453
        String action = null;
2454

    
2455
        // Parse the multipart form, and save the parameters in a Hashtable and
2456
        // save the FileParts in a hashtable
2457

    
2458
        Hashtable params = new Hashtable();
2459
        Hashtable fileList = new Hashtable();
2460
        int sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit")))
2461
                .intValue();
2462
        logMetacat.info(
2463
                "The limit size of data file is: " + sizeLimit);
2464

    
2465
        try {
2466
            // MBJ: need to put filesize limit in Metacat config
2467
            // (metacat.properties)
2468
            MultipartParser mp = new MultipartParser(request,
2469
                    sizeLimit * 1024 * 1024);
2470
            Part part;
2471
            while ((part = mp.readNextPart()) != null) {
2472
                String name = part.getName();
2473

    
2474
                if (part.isParam()) {
2475
                    // it's a parameter part
2476
                    ParamPart paramPart = (ParamPart) part;
2477
                    String value = paramPart.getStringValue();
2478
                    params.put(name, value);
2479
                    if (name.equals("action")) {
2480
                        action = value;
2481
                    }
2482
                } else if (part.isFile()) {
2483
                    // it's a file part
2484
                    FilePart filePart = (FilePart) part;
2485
                    fileList.put(name, filePart);
2486

    
2487
                    // Stop once the first file part is found, otherwise going
2488
                    // onto the
2489
                    // next part prevents access to the file contents. So...for
2490
                    // upload
2491
                    // to work, the datafile must be the last part
2492
                    break;
2493
                }
2494
            }
2495
        } catch (IOException ioe) {
2496
            try {
2497
                out = response.getWriter();
2498
            } catch (IOException ioe2) {
2499
                logMetacat.fatal("Fatal Error: couldn't get response output stream.");
2500
            }
2501
            out.println("<?xml version=\"1.0\"?>");
2502
            out.println("<error>");
2503
            out.println("Error: problem reading multipart data.");
2504
            out.println("</error>");
2505
        }
2506

    
2507
        // Get the session information
2508
        String username = null;
2509
        String password = null;
2510
        String[] groupnames = null;
2511
        String sess_id = null;
2512

    
2513
        // be aware of session expiration on every request
2514
        HttpSession sess = request.getSession(true);
2515
        if (sess.isNew()) {
2516
            // session expired or has not been stored b/w user requests
2517
            username = "public";
2518
            sess.setAttribute("username", username);
2519
        } else {
2520
            username = (String) sess.getAttribute("username");
2521
            password = (String) sess.getAttribute("password");
2522
            groupnames = (String[]) sess.getAttribute("groupnames");
2523
            try {
2524
                sess_id = (String) sess.getId();
2525
            } catch (IllegalStateException ise) {
2526
                System.out
2527
                        .println("error in  handleMultipartForm: this shouldn't "
2528
                                + "happen: the session should be valid: "
2529
                                + ise.getMessage());
2530
            }
2531
        }
2532

    
2533
        // Get the out stream
2534
        try {
2535
            out = response.getWriter();
2536
        } catch (IOException ioe2) {
2537
            logMetacat.error("Fatal Error: couldn't get response "
2538
                    + "output stream.");
2539
        }
2540

    
2541
        if (action.equals("upload")) {
2542
            if (username != null && !username.equals("public")) {
2543
                handleUploadAction(request, out, params, fileList, username,
2544
                        groupnames);
2545
            } else {
2546

    
2547
                out.println("<?xml version=\"1.0\"?>");
2548
                out.println("<error>");
2549
                out.println("Permission denied for " + action);
2550
                out.println("</error>");
2551
            }
2552
        } else {
2553
            /*
2554
             * try { out = response.getWriter(); } catch (IOException ioe2) {
2555
             * System.err.println("Fatal Error: couldn't get response output
2556
             * stream.");
2557
             */
2558
            out.println("<?xml version=\"1.0\"?>");
2559
            out.println("<error>");
2560
            out.println(
2561
                    "Error: action not registered.  Please report this error.");
2562
            out.println("</error>");
2563
        }
2564
        out.close();
2565
    }
2566

    
2567
    /**
2568
     * Handle the upload action by saving the attached file to disk and
2569
     * registering it in the Metacat db
2570
     */
2571
    private void handleUploadAction(HttpServletRequest request,
2572
            PrintWriter out, Hashtable params, Hashtable fileList,
2573
            String username, String[] groupnames)
2574
    {
2575
        //PrintWriter out = null;
2576
        //Connection conn = null;
2577
        String action = null;
2578
        String docid = null;
2579

    
2580
        /*
2581
         * response.setContentType("text/xml"); try { out =
2582
         * response.getWriter(); } catch (IOException ioe2) {
2583
         * System.err.println("Fatal Error: couldn't get response output
2584
         * stream.");
2585
         */
2586

    
2587
        if (params.containsKey("docid")) {
2588
            docid = (String) params.get("docid");
2589
        }
2590

    
2591
        // Make sure we have a docid and datafile
2592
        if (docid != null && fileList.containsKey("datafile")) {
2593
            logMetacat.warn("Uploading data docid: " + docid);
2594
            // Get a reference to the file part of the form
2595
            FilePart filePart = (FilePart) fileList.get("datafile");
2596
            String fileName = filePart.getFileName();
2597
            logMetacat.warn("Uploading filename: " + fileName);
2598
            // Check if the right file existed in the uploaded data
2599
            if (fileName != null) {
2600

    
2601
                try {
2602
                    //logMetacat.info("Upload datafile " + docid
2603
                    // +"...", 10);
2604
                    //If document get lock data file grant
2605
                    if (DocumentImpl.getDataFileLockGrant(docid)) {
2606
                        // Save the data file to disk using "docid" as the name
2607
                        String datafilepath = MetaCatUtil.getOption("datafilepath");
2608
                        File dataDirectory = new File(datafilepath);
2609
                        dataDirectory.mkdirs();
2610
                        File newFile = null;
2611
                        long size = 0;
2612
                        try
2613
                        {
2614
                          newFile = new File(dataDirectory, docid);
2615
                          size = filePart.writeTo(newFile);
2616
                        
2617
//                        register the file in the database (which generates
2618
                          // an exception
2619
                          //if the docid is not acceptable or other untoward
2620
                          // things happen
2621
                          DocumentImpl.registerDocument(fileName, "BIN", docid,
2622
                                username, groupnames);
2623
                        }
2624
                        catch (Exception ee)
2625
                        {
2626
                           //detelte the file to create
2627
                            newFile.delete();
2628
                            throw ee;
2629
                        }
2630

    
2631
                        EventLog.getInstance().log(request.getRemoteAddr(),
2632
                                username, docid, "upload");
2633
                        // Force replication this data file
2634
                        // To data file, "insert" and update is same
2635
                        // The fourth parameter is null. Because it is
2636
                        // notification server
2637
                        // and this method is in MetaCatServerlet. It is
2638
                        // original command,
2639
                        // not get force replication info from another metacat
2640
                        ForceReplicationHandler frh = new ForceReplicationHandler(
2641
                                docid, "insert", false, null);
2642

    
2643
                        // set content type and other response header fields
2644
                        // first
2645
                        out.println("<?xml version=\"1.0\"?>");
2646
                        out.println("<success>");
2647
                        out.println("<docid>" + docid + "</docid>");
2648
                        out.println("<size>" + size + "</size>");
2649
                        out.println("</success>");
2650
                    }
2651

    
2652
                } catch (Exception e) {
2653
                    
2654
                    out.println("<?xml version=\"1.0\"?>");
2655
                    out.println("<error>");
2656
                    out.println(e.getMessage());
2657
                    out.println("</error>");
2658
                }
2659
            } else {
2660
                // the field did not contain a file
2661
                out.println("<?xml version=\"1.0\"?>");
2662
                out.println("<error>");
2663
                out.println("The uploaded data did not contain a valid file.");
2664
                out.println("</error>");
2665
            }
2666
        } else {
2667
            // Error bcse docid missing or file missing
2668
            out.println("<?xml version=\"1.0\"?>");
2669
            out.println("<error>");
2670
            out.println("The uploaded data did not contain a valid docid "
2671
                    + "or valid file.");
2672
            out.println("</error>");
2673
        }
2674
    }
2675

    
2676
    /*
2677
     * A method to handle set access action
2678
     */
2679
    private void handleSetAccessAction(PrintWriter out, Hashtable params,
2680
            String username)
2681
    {
2682
        String[] docList = null;
2683
        String[] principalList = null;
2684
        String[] permissionList = null;
2685
        String[] permTypeList = null;
2686
        String[] permOrderList = null;
2687
        String permission = null;
2688
        String permType = null;
2689
        String permOrder = null;
2690
        Vector errorList = new Vector();
2691
        String error = null;
2692
        Vector successList = new Vector();
2693
        String success = null;
2694

    
2695
        // Get parameters
2696
        if (params.containsKey("docid")) {
2697
            docList = (String[]) params.get("docid");
2698
        }
2699
        if (params.containsKey("principal")) {
2700
            principalList = (String[]) params.get("principal");
2701
        }
2702
        if (params.containsKey("permission")) {
2703
            permissionList = (String[]) params.get("permission");
2704

    
2705
        }
2706
        if (params.containsKey("permType")) {
2707
            permTypeList = (String[]) params.get("permType");
2708

    
2709
        }
2710
        if (params.containsKey("permOrder")) {
2711
            permOrderList = (String[]) params.get("permOrder");
2712

    
2713
        }
2714

    
2715
        // Make sure the parameter is not null
2716
        if (docList == null || principalList == null || permTypeList == null
2717
                || permissionList == null) {
2718
            error = "Please check your parameter list, it should look like: "
2719
                    + "?action=setaccess&docid=pipeline.1.1&principal=public"
2720
                    + "&permission=read&permType=allow&permOrder=allowFirst";
2721
            errorList.addElement(error);
2722
            outputResponse(successList, errorList, out);
2723
            return;
2724
        }
2725

    
2726
        // Only select first element for permission, type and order
2727
        permission = permissionList[0];
2728
        permType = permTypeList[0];
2729
        if (permOrderList != null) {
2730
            permOrder = permOrderList[0];
2731
        }
2732

    
2733
        // Get package doctype set
2734
        Vector packageSet = MetaCatUtil.getOptionList(MetaCatUtil
2735
                .getOption("packagedoctypeset"));
2736
        //debug
2737
        if (packageSet != null) {
2738
            for (int i = 0; i < packageSet.size(); i++) {
2739
                logMetacat.info("doctype in package set: "
2740
                        + (String) packageSet.elementAt(i));
2741
            }
2742
        }
2743

    
2744
        // handle every accessionNumber
2745
        for (int i = 0; i < docList.length; i++) {
2746
            String accessionNumber = docList[i];
2747
            String owner = null;
2748
            String publicId = null;
2749
            // Get document owner and public id
2750
            try {
2751
                owner = getFieldValueForDoc(accessionNumber, "user_owner");
2752
                publicId = getFieldValueForDoc(accessionNumber, "doctype");
2753
            } catch (Exception e) {
2754
                logMetacat.error("Error in handleSetAccessAction: "
2755
                        + e.getMessage());
2756
                error = "Error in set access control for document - "
2757
                        + accessionNumber + e.getMessage();
2758
                errorList.addElement(error);
2759
                continue;
2760
            }
2761
            //check if user is the owner. Only owner can do owner
2762
            if (username == null || owner == null || !username.equals(owner)) {
2763
                error = "User - " + username
2764
                        + " does not have permission to set "
2765
                        + "access control for docid - " + accessionNumber;
2766
                errorList.addElement(error);
2767
                continue;
2768
            }
2769

    
2770
            // If docid publicid is BIN data file or other beta4, 6 package
2771
            // document
2772
            // we could not do set access control. Because we don't want
2773
            // inconsistent
2774
            // to its access docuemnt
2775
            if (publicId != null && packageSet != null
2776
                    && packageSet.contains(publicId)) {
2777
                error = "Could not set access control to document "
2778
                        + accessionNumber
2779
                        + "because it is in a pakcage and it has a access file for it";
2780
                errorList.addElement(error);
2781
                continue;
2782
            }
2783

    
2784
            // for every principle
2785
            for (int j = 0; j < principalList.length; j++) {
2786
                String principal = principalList[j];
2787
                try {
2788
                    //insert permission
2789
                    AccessControlForSingleFile accessControl = new AccessControlForSingleFile(
2790
                            accessionNumber, principal, permission, permType,
2791
                            permOrder);
2792
                    accessControl.insertPermissions();
2793
                    success = "Set access control to document "
2794
                            + accessionNumber + " successfully";
2795
                    successList.addElement(success);
2796
                } catch (Exception ee) {
2797
                    logMetacat.error(
2798
                            "Erorr in handleSetAccessAction2: "
2799
                                    + ee.getMessage());
2800
                    error = "Faild to set access control for document "
2801
                            + accessionNumber + " because " + ee.getMessage();
2802
                    errorList.addElement(error);
2803
                    continue;
2804
                }
2805
            }
2806
        }
2807
        outputResponse(successList, errorList, out);
2808
    }
2809

    
2810
    /*
2811
     * A method try to determin a docid's public id, if couldn't find null will
2812
     * be returned.
2813
     */
2814
    private String getFieldValueForDoc(String accessionNumber, String fieldName)
2815
            throws Exception
2816
    {
2817
        if (accessionNumber == null || accessionNumber.equals("")
2818
                || fieldName == null || fieldName.equals("")) { throw new Exception(
2819
                "Docid or field name was not specified"); }
2820

    
2821
        PreparedStatement pstmt = null;
2822
        ResultSet rs = null;
2823
        String fieldValue = null;
2824
        String docId = null;
2825
        DBConnection conn = null;
2826
        int serialNumber = -1;
2827

    
2828
        // get rid of revision if access number has
2829
        docId = MetaCatUtil.getDocIdFromString(accessionNumber);
2830
        try {
2831
            //check out DBConnection
2832
            conn = DBConnectionPool
2833
                    .getDBConnection("MetaCatServlet.getPublicIdForDoc");
2834
            serialNumber = conn.getCheckOutSerialNumber();
2835
            pstmt = conn.prepareStatement("SELECT " + fieldName
2836
                    + " FROM xml_documents " + "WHERE docid = ? ");
2837

    
2838
            pstmt.setString(1, docId);
2839
            pstmt.execute();
2840
            rs = pstmt.getResultSet();
2841
            boolean hasRow = rs.next();
2842
            int perm = 0;
2843
            if (hasRow) {
2844
                fieldValue = rs.getString(1);
2845
            } else {
2846
                throw new Exception("Could not find document: "
2847
                        + accessionNumber);
2848
            }
2849
        } catch (Exception e) {
2850
            logMetacat.error(
2851
                    "Exception in MetacatServlet.getPublicIdForDoc: "
2852
                            + e.getMessage());
2853
            throw e;
2854
        } finally {
2855
            try {
2856
                rs.close();
2857
                pstmt.close();
2858

    
2859
            } finally {
2860
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2861
            }
2862
        }
2863
        return fieldValue;
2864
    }
2865

    
2866
    /*
2867
     * Get the list of documents from the database and return the list in an
2868
     * Vector of identifiers.
2869
     *
2870
     * @ returns the array of identifiers
2871
     */
2872
    private Vector getDocumentList() throws SQLException
2873
    {
2874
        Vector docList = new Vector();
2875
        PreparedStatement pstmt = null;
2876
        ResultSet rs = null;
2877
        DBConnection conn = null;
2878
        int serialNumber = -1;
2879

    
2880
        try {
2881
            //check out DBConnection
2882
            conn = DBConnectionPool
2883
                    .getDBConnection("MetaCatServlet.getDocumentList");
2884
            serialNumber = conn.getCheckOutSerialNumber();
2885
            pstmt = conn.prepareStatement("SELECT docid, rev"
2886
                    + " FROM xml_documents ");
2887
            pstmt.execute();
2888
            rs = pstmt.getResultSet();
2889
            while (rs.next()) {
2890
                String docid = rs.getString(1);
2891
                String rev = rs.getString(2);
2892
                docList.add(docid + "." + rev);
2893
            }
2894
        } catch (SQLException e) {
2895
            logMetacat.error(
2896
                    "Exception in MetacatServlet.getDocumentList: "
2897
                            + e.getMessage());
2898
            throw e;
2899
        } finally {
2900
            try {
2901
                rs.close();
2902
                pstmt.close();
2903

    
2904
            } catch (SQLException se) {
2905
                logMetacat.error(
2906
                    "Exception in MetacatServlet.getDocumentList: "
2907
                            + se.getMessage());
2908
                throw se;
2909
            } finally {
2910
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2911
            }
2912
        }
2913
        return docList;
2914
    }
2915

    
2916
    /*
2917
     * A method to output setAccess action result
2918
     */
2919
    private void outputResponse(Vector successList, Vector errorList,
2920
            PrintWriter out)
2921
    {
2922
        boolean error = false;
2923
        boolean success = false;
2924
        // Output prolog
2925
        out.println(PROLOG);
2926
        // output success message
2927
        if (successList != null) {
2928
            for (int i = 0; i < successList.size(); i++) {
2929
                out.println(SUCCESS);
2930
                out.println((String) successList.elementAt(i));
2931
                out.println(SUCCESSCLOSE);
2932
                success = true;
2933
            }
2934
        }
2935
        // output error message
2936
        if (errorList != null) {
2937
            for (int i = 0; i < errorList.size(); i++) {
2938
                out.println(ERROR);
2939
                out.println((String) errorList.elementAt(i));
2940
                out.println(ERRORCLOSE);
2941
                error = true;
2942
            }
2943
        }
2944

    
2945
        // if no error and no success info, send a error that nothing happened
2946
        if (!error && !success) {
2947
            out.println(ERROR);
2948
            out.println("Nothing happend for setaccess action");
2949
            out.println(ERRORCLOSE);
2950
        }
2951
    }
2952
    
2953
    /**
2954
     * Method to get session table which store the session info
2955
     * @return
2956
     */
2957
    public static Hashtable getSessionHash()
2958
    {
2959
        return sessionHash;
2960
    }
2961
    
2962
    /*
2963
     * If the given docid only have one seperter, we need 
2964
     * append rev for it. The rev come from xml_documents
2965
     */
2966
    private static String appendRev(String docid) throws Exception
2967
    {
2968
        String newAccNum = null;
2969
        String separator = MetaCatUtil.getOption("accNumSeparator");
2970
        int firstIndex = docid.indexOf(separator);
2971
        int lastIndex = docid.lastIndexOf(separator);
2972
        if (firstIndex == lastIndex)
2973
        {
2974
            
2975
           //only one seperater
2976
            int rev = DBUtil.getLatestRevisionInDocumentTable(docid);
2977
            if (rev == -1)
2978
            {
2979
                throw new Exception("Couldn't find the document "+docid);
2980
            }
2981
            else
2982
            {
2983
                newAccNum = docid+ separator+ rev;
2984
            }
2985
        }
2986
        else
2987
        {
2988
            // in other suituation we don't change the docid
2989
            newAccNum = docid;
2990
        }
2991
        logMetacat.warn("The docid will be read is "+newAccNum);
2992
        return newAccNum;
2993
    }
2994
}
(44-44/65)