Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements a metadata catalog as a java Servlet
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Matt Jones, Dan Higgins, Jivka Bojilova, Chad Berkley
7
 *    Release: @release@
8
 *
9
 *   '$Author: sgarg $'
10
 *     '$Date: 2005-11-10 13:34:44 -0800 (Thu, 10 Nov 2005) $'
11
 * '$Revision: 2729 $'
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.PropertyResourceBundle;
48
import java.util.Vector;
49
import java.util.zip.ZipEntry;
50
import java.util.zip.ZipOutputStream;
51
import java.util.Timer;
52

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

    
62
import org.ecoinformatics.eml.EMLParser;
63

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

    
69
import org.apache.log4j.Logger;
70
import org.apache.log4j.PropertyConfigurator;
71

    
72
import edu.ucsb.nceas.utilities.Options;
73

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

    
121
    private ServletConfig config = null;
122

    
123
    private ServletContext context = null;
124

    
125
    private String resultStyleURL = null;
126

    
127
    private String xmlcatalogfile = null;
128

    
129
    private String saxparser = null;
130

    
131
    private String datafilepath = null;
132

    
133
    private File dataDirectory = null;
134

    
135
    private String servletpath = null;
136

    
137
    private String htmlpath = null;
138

    
139
    private PropertyResourceBundle options = null;
140

    
141
    private MetaCatUtil util = null;
142

    
143
    private DBConnectionPool connPool = null;
144

    
145
    private static Hashtable sessionHash = new Hashtable();
146

    
147
    private static final String PROLOG = "<?xml version=\"1.0\"?>";
148

    
149
    private static final String SUCCESS = "<success>";
150

    
151
    private static final String SUCCESSCLOSE = "</success>";
152

    
153
    private static final String ERROR = "<error>";
154

    
155
    private static final String ERRORCLOSE = "</error>";
156

    
157
    public static final String SCHEMALOCATIONKEYWORD = ":schemaLocation";
158

    
159
    public static final String NONAMESPACELOCATION = ":noNamespaceSchemaLocation";
160

    
161
    public static final String NAMESPACEKEYWORD = "xmlns";
162

    
163
    public static final String EML2KEYWORD = ":eml";
164

    
165
    public static final String XMLFORMAT = "xml";
166

    
167
    private static final String CONFIG_DIR = "WEB-INF";
168

    
169
    private static final String CONFIG_NAME = "metacat.properties";
170
     	 
171
    private static Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
172
       
173
    private Timer timer = null;
174
    
175
    /**
176
     * Initialize the servlet by creating appropriate database connections
177
     */
178
    public void init(ServletConfig config) throws ServletException
179
    {
180
        try {
181
            super.init(config);
182
            this.config = config;
183
            this.context = config.getServletContext();
184

    
185
            // Initialize the properties file for our options
186
            String dirPath = context.getRealPath(CONFIG_DIR);
187
            File propertyFile = new File(dirPath, CONFIG_NAME);
188

    
189
            String LOG_CONFIG_NAME = dirPath + "/log4j.properties";
190
            PropertyConfigurator.configureAndWatch(LOG_CONFIG_NAME);
191
            
192
            Options options = null;
193
            try {
194
                options = Options.initialize(propertyFile);
195
                MetaCatUtil.printMessage("Options configured: "
196
                        + options.getOption("configured"));
197
            } catch (IOException ioe) {
198
                logMetacat.error("Error in loading options: "
199
                        + ioe.getMessage());
200
            }
201

    
202
            util = new MetaCatUtil();
203

    
204
            //initial DBConnection pool
205
            connPool = DBConnectionPool.getInstance();
206

    
207
            // Get the configuration file information
208
            resultStyleURL = MetaCatUtil.getOption("resultStyleURL");
209
            xmlcatalogfile = MetaCatUtil.getOption("xmlcatalogfile");
210
            saxparser = MetaCatUtil.getOption("saxparser");
211
            datafilepath = MetaCatUtil.getOption("datafilepath");
212
            dataDirectory = new File(datafilepath);
213
            servletpath = MetaCatUtil.getOption("servletpath");
214
            htmlpath = MetaCatUtil.getOption("htmlpath");
215

    
216
            // Index the paths specified in the metacat.properties
217
            checkIndexPaths();
218

    
219
            // initiate the indexing Queue
220
            IndexingQueue.getInstance();
221
            
222
            // start the IndexingThread if indexingTimerTaskTime more than 0. 
223
            // It will index all the documents not yet indexed in the database             
224
            int indexingTimerTaskTime = Integer.parseInt(MetaCatUtil.getOption("indexingTimerTaskTime"));
225
            if(indexingTimerTaskTime > 0){
226
            	timer = new Timer();
227
            	timer.schedule(new IndexingTimerTask(), 0, indexingTimerTaskTime);
228
            }
229
            
230
            MetaCatUtil.printMessage("Metacat (" + Version.getVersion()
231
                               + ") initialized.");
232

    
233
        } catch (ServletException ex) {
234
            throw ex;
235
        } catch (SQLException e) {
236
            logMetacat.error("Error in MetacatServlet.init: "
237
                    + e.getMessage());
238
        }
239
    }
240

    
241
    /**
242
     * Close all db connections from the pool
243
     */
244
    public void destroy()
245
    {
246
        // Close all db connection
247
        System.out.println("Destroying MetacatServlet");
248
        DBConnectionPool.release();
249
        timer.cancel();
250
    }
251

    
252
    /** Handle "GET" method requests from HTTP clients */
253
    public void doGet(HttpServletRequest request, HttpServletResponse response)
254
            throws ServletException, IOException
255
    {
256

    
257
        // Process the data and send back the response
258
        handleGetOrPost(request, response);
259
    }
260

    
261
    /** Handle "POST" method requests from HTTP clients */
262
    public void doPost(HttpServletRequest request, HttpServletResponse response)
263
            throws ServletException, IOException
264
    {
265

    
266
        // Process the data and send back the response
267
        handleGetOrPost(request, response);
268
    }
269

    
270
    /**
271
     * Index the paths specified in the metacat.properties
272
     */
273
    private void checkIndexPaths(){
274
        MetaCatUtil.pathsForIndexing
275
            = MetaCatUtil.getOptionList(MetaCatUtil.getOption("indexed_paths"));
276
    
277
        if (MetaCatUtil.pathsForIndexing != null) {
278
    
279
            MetaCatUtil.printMessage("Indexing paths specified in metacat.properties....");
280
    
281
            DBConnection conn = null;
282
            int serialNumber = -1;
283
            PreparedStatement pstmt = null;
284
            PreparedStatement pstmt1 = null;
285
            ResultSet rs = null;
286
    
287
            for (int i = 0; i < MetaCatUtil.pathsForIndexing.size(); i++) {
288
                logMetacat.info("Checking if '"
289
                           + (String) MetaCatUtil.pathsForIndexing.elementAt(i)
290
                           + "' is indexed.... ");
291
    
292
                try {
293
                    //check out DBConnection
294
                    conn = DBConnectionPool.
295
                        getDBConnection("MetaCatServlet.checkIndexPaths");
296
                    serialNumber = conn.getCheckOutSerialNumber();
297
    
298
                    pstmt = conn.prepareStatement(
299
                        "SELECT * FROM xml_path_index " + "WHERE path = ?");
300
                    pstmt.setString(1, (String) MetaCatUtil.pathsForIndexing
301
                                    .elementAt(i));
302
    
303
                    pstmt.execute();
304
                    rs = pstmt.getResultSet();
305
    
306
                    if (!rs.next()) {
307
                        logMetacat.info(".....not indexed yet.");
308
                        rs.close();
309
                        pstmt.close();
310
                        conn.increaseUsageCount(1);
311
    
312
                        logMetacat.debug(
313
                              "Inserting following path in xml_path_index: "
314
                              + (String)MetaCatUtil.pathsForIndexing
315
                                                   .elementAt(i));
316
    
317
                        pstmt = conn.prepareStatement("SELECT DISTINCT n.docid, "
318
                              + "n.nodedata, n.nodedatanumerical, n.parentnodeid"
319
                              + " FROM xml_nodes n, xml_index i WHERE"
320
                              + " i.path = ? and n.parentnodeid=i.nodeid and"
321
                              + " n.nodetype LIKE 'TEXT' order by n.parentnodeid");
322
                        pstmt.setString(1, (String) MetaCatUtil.
323
                                        pathsForIndexing.elementAt(i));
324
                        pstmt.execute();
325
                        rs = pstmt.getResultSet();
326
    
327
                        int count = 0;
328
                        logMetacat.debug(
329
                                       "Executed the select statement for: "
330
                                       + (String) MetaCatUtil.pathsForIndexing
331
                                         .elementAt(i));
332
    
333
                        try {
334
                            while (rs.next()) {
335
    
336
                                String docid = rs.getString(1);
337
                                String nodedata = rs.getString(2);
338
                                float nodedatanumerical = rs.getFloat(3);
339
                                int parentnodeid = rs.getInt(4);
340
    
341
                                if (!nodedata.trim().equals("")) {
342
                                    pstmt1 = conn.prepareStatement(
343
                                        "INSERT INTO xml_path_index"
344
                                        + " (docid, path, nodedata, "
345
                                        + "nodedatanumerical, parentnodeid)"
346
                                        + " VALUES (?, ?, ?, ?, ?)");
347
    
348
                                    pstmt1.setString(1, docid);
349
                                    pstmt1.setString(2, (String) MetaCatUtil.
350
                                                pathsForIndexing.elementAt(i));
351
                                    pstmt1.setString(3, nodedata);
352
                                    pstmt1.setFloat(4, nodedatanumerical);
353
                                    pstmt1.setInt(5, parentnodeid);
354
    
355
                                    pstmt1.execute();
356
                                    pstmt1.close();
357
    
358
                                    count++;
359
    
360
                                }
361
                            }
362
                        }
363
                        catch (Exception e) {
364
                            System.out.println("Exception:" + e.getMessage());
365
                            e.printStackTrace();
366
                        }
367
    
368
                        rs.close();
369
                        pstmt.close();
370
                        conn.increaseUsageCount(1);
371
    
372
                        logMetacat.warn("Indexed " + count
373
                                + " records from xml_nodes for '"
374
                                + (String) MetaCatUtil.pathsForIndexing.elementAt(i)
375
                                + "'");
376
    
377
                    } else {
378
                    	logMetacat.info(".....already indexed.");
379
                    }
380
    
381
                    rs.close();
382
                    pstmt.close();
383
                    conn.increaseUsageCount(1);
384
    
385
                } catch (Exception e) {
386
                    logMetacat.error("Error in MetaCatServlet.checkIndexPaths: "
387
                                             + e.getMessage());
388
                }finally {
389
                    //check in DBonnection
390
                    DBConnectionPool.returnDBConnection(conn, serialNumber);
391
                }
392
    
393
    
394
            }
395
    
396
            MetaCatUtil.printMessage("Path Indexing Completed");
397
        }
398
    }    
399

    
400
    /**
401
     * Control servlet response depending on the action parameter specified
402
     */
403
    private void handleGetOrPost(HttpServletRequest request,
404
            HttpServletResponse response) throws ServletException, IOException
405
    {
406

    
407
        if (util == null) {
408
            util = new MetaCatUtil();
409
        }
410
        /*
411
         * logMetacat.info("Connection pool size: "
412
         * +connPool.getSizeOfDBConnectionPool(),10);
413
         * logMetacat.info("Free DBConnection number: "
414
         */
415
        //If all DBConnection in the pool are free and DBConnection pool
416
        //size is greater than initial value, shrink the connection pool
417
        //size to initial value
418
        DBConnectionPool.shrinkDBConnectionPoolSize();
419

    
420
        //Debug message to print out the method which have a busy DBConnection
421
        connPool.printMethodNameHavingBusyDBConnection();
422

    
423
        String ctype = request.getContentType();
424
        if (ctype != null && ctype.startsWith("multipart/form-data")) {
425
            handleMultipartForm(request, response);
426
        } else {
427

    
428
            String name = null;
429
            String[] value = null;
430
            String[] docid = new String[3];
431
            Hashtable params = new Hashtable();
432
            Enumeration paramlist = request.getParameterNames();
433

    
434
            while (paramlist.hasMoreElements()) {
435

    
436
                name = (String) paramlist.nextElement();
437
                value = request.getParameterValues(name);
438

    
439
                // Decode the docid and mouse click information
440
                if (name.endsWith(".y")) {
441
                    docid[0] = name.substring(0, name.length() - 2);
442
                    params.put("docid", docid);
443
                    name = "ypos";
444
                }
445
                if (name.endsWith(".x")) {
446
                    name = "xpos";
447
                }
448

    
449
                params.put(name, value);
450
            }
451

    
452
            //handle param is emptpy
453
            if (params.isEmpty() || params == null) { return; }
454

    
455
            //if the user clicked on the input images, decode which image
456
            //was clicked then set the action.
457
            if(params.get("action") == null){
458
                PrintWriter out = response.getWriter();
459
                response.setContentType("text/xml");
460
                out.println("<?xml version=\"1.0\"?>");
461
                out.println("<error>");
462
                out.println("Action not specified");
463
                out.println("</error>");
464
                out.close();
465
                return;
466
            }
467

    
468
            String action = ((String[]) params.get("action"))[0];
469
            logMetacat.warn("Action is: " + action);
470

    
471
            // This block handles session management for the servlet
472
            // by looking up the current session information for all actions
473
            // other than "login" and "logout"
474
            String username = null;
475
            String password = null;
476
            String[] groupnames = null;
477
            String sess_id = null;
478
            name = null;
479
            
480
            // handle login action
481
            if (action.equals("login")) {
482
                PrintWriter out = response.getWriter();
483
                handleLoginAction(out, params, request, response);
484
                out.close();
485

    
486
                // handle logout action
487
            } else if (action.equals("logout")) {
488
                PrintWriter out = response.getWriter();
489
                handleLogoutAction(out, params, request, response);
490
                out.close();
491

    
492
                // handle shrink DBConnection request
493
            } else if (action.equals("shrink")) {
494
                PrintWriter out = response.getWriter();
495
                boolean success = false;
496
                //If all DBConnection in the pool are free and DBConnection
497
                // pool
498
                //size is greater than initial value, shrink the connection
499
                // pool
500
                //size to initial value
501
                success = DBConnectionPool.shrinkConnectionPoolSize();
502
                if (success) {
503
                    //if successfully shrink the pool size to initial value
504
                    out.println("DBConnection Pool shrunk successfully.");
505
                }//if
506
                else {
507
                    out.println("DBConnection pool not shrunk successfully.");
508
                }
509
                //close out put
510
                out.close();
511

    
512
                // aware of session expiration on every request
513
            } else {
514
                HttpSession sess = request.getSession(true);
515
                if (sess.isNew() && !params.containsKey("sessionid")) {
516
                    // session expired or has not been stored b/w user requests
517
                    logMetacat.warn(
518
                            "The session is new or no sessionid is assigned. The user is public");
519
                    username = "public";
520
                    sess.setAttribute("username", username);
521
                } else {
522
                    logMetacat.warn("The session is either old or "
523
                            + "has sessionid parameter");
524
                    try {
525
                        if (params.containsKey("sessionid")) {
526
                            sess_id = ((String[]) params.get("sessionid"))[0];
527
                            logMetacat.info("in has sessionid "
528
                                    + sess_id);
529
                            if (sessionHash.containsKey(sess_id)) {
530
                                logMetacat.info("find the id "
531
                                        + sess_id + " in hash table");
532
                                sess = (HttpSession) sessionHash.get(sess_id);
533
                            }
534
                        } else {
535
                            // we already store the session in login, so we
536
                            // don't need here
537
                            /*
538
                             * logMetacat.info("in no sessionid
539
                             * parameter ", 40); sess_id =
540
                             * (String)sess.getId();
541
                             * logMetacat.info("storing the session id "
542
                             * + sess_id + " which has username " +
543
                             * sess.getAttribute("username") + " into session
544
                             * hash in handleGetOrPost method", 35);
545
                             */
546
                        }
547
                    } catch (IllegalStateException ise) {
548
                        logMetacat.error(
549
                                "Error in handleGetOrPost: this shouldn't "
550
                                + "happen: the session should be valid: "
551
                                + ise.getMessage());
552
                    }
553

    
554
                    username = (String) sess.getAttribute("username");
555
                    logMetacat.info("The user name from session is: "
556
                            + username);
557
                    password = (String) sess.getAttribute("password");
558
                    groupnames = (String[]) sess.getAttribute("groupnames");
559
                    name = (String) sess.getAttribute("name");
560
                }
561

    
562
                //make user user username should be public
563
                if (username == null || (username.trim().equals(""))) {
564
                    username = "public";
565
                }
566
                logMetacat.warn("The user is : " + username);
567
            }
568
            // Now that we know the session is valid, we can delegate the
569
            // request
570
            // to a particular action handler
571
            if (action.equals("query")) {
572
                PrintWriter out = response.getWriter();
573
                handleQuery(out, params, response, username, groupnames,
574
                        sess_id);
575
                out.close();
576
            } else if (action.equals("squery")) {
577
                PrintWriter out = response.getWriter();
578
                if (params.containsKey("query")) {
579
                    handleSQuery(out, params, response, username, groupnames,
580
                            sess_id);
581
                    out.close();
582
                } else {
583
                    out.println(
584
                            "Illegal action squery without \"query\" parameter");
585
                    out.close();
586
                }
587
            } else if (action.equals("export")) {
588

    
589
                handleExportAction(params, response, username,
590
                        groupnames, password);
591
            } else if (action.equals("read")) {
592
                handleReadAction(params, request, response, username, password,
593
                        groupnames);
594
            } else if (action.equals("readinlinedata")) {
595
                handleReadInlineDataAction(params, request, response, username,
596
                        password, groupnames);
597
            } else if (action.equals("insert") || action.equals("update")) {
598
                PrintWriter out = response.getWriter();
599
                if ((username != null) && !username.equals("public")) {
600
                    handleInsertOrUpdateAction(request, response,
601
                            out, params, username, groupnames);
602
                } else {
603
                    response.setContentType("text/xml");
604
                    out.println("<?xml version=\"1.0\"?>");
605
                    out.println("<error>");
606
                    out.println("Permission denied for user " + username + " "
607
                            + action);
608
                    out.println("</error>");
609
                }
610
                out.close();
611
            } else if (action.equals("delete")) {
612
                PrintWriter out = response.getWriter();
613
                if ((username != null) && !username.equals("public")) {
614
                    handleDeleteAction(out, params, request, response, username,
615
                            groupnames);
616
                } else {
617
                    response.setContentType("text/xml");
618
                    out.println("<?xml version=\"1.0\"?>");
619
                    out.println("<error>");
620
                    out.println("Permission denied for " + action);
621
                    out.println("</error>");
622
                }
623
                out.close();
624
            } else if (action.equals("validate")) {
625
                PrintWriter out = response.getWriter();
626
                handleValidateAction(out, params);
627
                out.close();
628
            } else if (action.equals("setaccess")) {
629
                PrintWriter out = response.getWriter();
630
                handleSetAccessAction(out, params, username);
631
                out.close();
632
            } else if (action.equals("getaccesscontrol")) {
633
                PrintWriter out = response.getWriter();
634
                handleGetAccessControlAction(out, params, response, username,
635
                        groupnames);
636
                out.close();
637
            } else if (action.equals("getprincipals")) {
638
                PrintWriter out = response.getWriter();
639
                handleGetPrincipalsAction(out, username, password);
640
                out.close();
641
            } else if (action.equals("getdoctypes")) {
642
                PrintWriter out = response.getWriter();
643
                handleGetDoctypesAction(out, params, response);
644
                out.close();
645
            } else if (action.equals("getdtdschema")) {
646
                PrintWriter out = response.getWriter();
647
                handleGetDTDSchemaAction(out, params, response);
648
                out.close();
649
            } else if (action.equals("getlastdocid")) {
650
                PrintWriter out = response.getWriter();
651
                handleGetMaxDocidAction(out, params, response);
652
                out.close();
653
            } else if (action.equals("getrevisionanddoctype")) {
654
                PrintWriter out = response.getWriter();
655
                handleGetRevisionAndDocTypeAction(out, params);
656
                out.close();
657
            } else if (action.equals("getversion")) {
658
                response.setContentType("text/xml");
659
                PrintWriter out = response.getWriter();
660
                out.println(Version.getVersionAsXml());
661
                out.close();
662
            } else if (action.equals("getlog")) {
663
                handleGetLogAction(params, request, response, username, groupnames);
664
            } else if (action.equals("getloggedinuserinfo")) {
665
                PrintWriter out = response.getWriter();
666
                response.setContentType("text/xml");
667
                out.println("<?xml version=\"1.0\"?>");
668
                out.println("\n<user>\n");
669
                out.println("\n<username>\n");
670
                out.println(username);
671
                out.println("\n</username>\n");
672
                if(name!=null){
673
                	out.println("\n<name>\n");
674
                	out.println(name);
675
                	out.println("\n</name>\n");
676
                }
677
                if(MetaCatUtil.isAdministrator(username, groupnames)){
678
                	out.println("<isAdministrator></isAdministrator>\n");	
679
                }
680
                if(MetaCatUtil.isModerator(username, groupnames)){
681
                	out.println("<isModerator></isModerator>\n");	
682
                }
683
                out.println("\n</user>\n");
684
                out.close();
685
            } else if (action.equals("buildindex")) {
686
                handleBuildIndexAction(params, request, response, username, groupnames);
687
            } else if (action.equals("login") || action.equals("logout")) {
688
                /*
689
            } else if (action.equals("protocoltest")) {
690
                String testURL = "metacat://dev.nceas.ucsb.edu/NCEAS.897766.9";
691
                try {
692
                    testURL = ((String[]) params.get("url"))[0];
693
                } catch (Throwable t) {
694
                }
695
                String phandler = System
696
                        .getProperty("java.protocol.handler.pkgs");
697
                response.setContentType("text/html");
698
                PrintWriter out = response.getWriter();
699
                out.println("<body bgcolor=\"white\">");
700
                out.println("<p>Handler property: <code>" + phandler
701
                        + "</code></p>");
702
                out.println("<p>Starting test for:<br>");
703
                out.println("    " + testURL + "</p>");
704
                try {
705
                    URL u = new URL(testURL);
706
                    out.println("<pre>");
707
                    out.println("Protocol: " + u.getProtocol());
708
                    out.println("    Host: " + u.getHost());
709
                    out.println("    Port: " + u.getPort());
710
                    out.println("    Path: " + u.getPath());
711
                    out.println("     Ref: " + u.getRef());
712
                    String pquery = u.getQuery();
713
                    out.println("   Query: " + pquery);
714
                    out.println("  Params: ");
715
                    if (pquery != null) {
716
                        Hashtable qparams = MetaCatUtil.parseQuery(u.getQuery());
717
                        for (Enumeration en = qparams.keys(); en
718
                                .hasMoreElements();) {
719
                            String pname = (String) en.nextElement();
720
                            String pvalue = (String) qparams.get(pname);
721
                            out.println("    " + pname + ": " + pvalue);
722
                        }
723
                    }
724
                    out.println("</pre>");
725
                    out.println("</body>");
726
                    out.close();
727
                } catch (MalformedURLException mue) {
728
                    System.out.println(
729
                            "bad url from MetacatServlet.handleGetOrPost");
730
                    out.println(mue.getMessage());
731
                    mue.printStackTrace(out);
732
                    out.close();
733
                }
734
                */
735
            } else {
736
                PrintWriter out = response.getWriter();
737
                out.println("<?xml version=\"1.0\"?>");
738
                out.println("<error>");
739
                out.println(
740
                     "Error: action not registered.  Please report this error.");
741
                out.println("</error>");
742
                out.close();
743
            }
744

    
745
            //util.closeConnections();
746
            // Close the stream to the client
747
            //out.close();
748
        }
749
    }
750

    
751
    // LOGIN & LOGOUT SECTION
752
    /**
753
     * Handle the login request. Create a new session object. Do user
754
     * authentication through the session.
755
     */
756
    private void handleLoginAction(PrintWriter out, Hashtable params,
757
            HttpServletRequest request, HttpServletResponse response)
758
    {
759

    
760
        AuthSession sess = null;
761

    
762
        if(params.get("username") == null){
763
            response.setContentType("text/xml");
764
            out.println("<?xml version=\"1.0\"?>");
765
            out.println("<error>");
766
            out.println("Username not specified");
767
            out.println("</error>");
768
            return;
769
        }
770

    
771
        if(params.get("password") == null){
772
            response.setContentType("text/xml");
773
            out.println("<?xml version=\"1.0\"?>");
774
            out.println("<error>");
775
            out.println("Password not specified");
776
            out.println("</error>");
777
            return;
778
        }
779

    
780
        String un = ((String[]) params.get("username"))[0];
781
        logMetacat.warn("user " + un + " is trying to login");
782
        String pw = ((String[]) params.get("password"))[0];
783

    
784
        String qformat = "xml";
785
        if(params.get("qformat") != null){
786
            qformat = ((String[]) params.get("qformat"))[0];
787
        }
788

    
789
        try {
790
            sess = new AuthSession();
791
        } catch (Exception e) {
792
            System.out.println("error in MetacatServlet.handleLoginAction: "
793
                    + e.getMessage());
794
            out.println(e.getMessage());
795
            return;
796
        }
797
        boolean isValid = sess.authenticate(request, un, pw);
798

    
799
        //if it is authernticate is true, store the session
800
        if (isValid) {
801
            HttpSession session = sess.getSessions();
802
            String id = session.getId();
803
            logMetacat.info("Store session id " + id
804
                    + "which has username" + session.getAttribute("username")
805
                    + " into hash in login method");
806
            sessionHash.put(id, session);
807
        }
808

    
809
        // format and transform the output
810
        if (qformat.equals("xml")) {
811
            response.setContentType("text/xml");
812
            out.println(sess.getMessage());
813
        } else {
814
            try {
815
                DBTransform trans = new DBTransform();
816
                response.setContentType("text/html");
817
                trans.transformXMLDocument(sess.getMessage(),
818
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
819
                        out, null);
820
            } catch (Exception e) {
821

    
822
                logMetacat.error(
823
                        "Error in MetaCatServlet.handleLoginAction: "
824
                                + e.getMessage());
825
            }
826
        }
827
    }
828

    
829
    /**
830
     * Handle the logout request. Close the connection.
831
     */
832
    private void handleLogoutAction(PrintWriter out, Hashtable params,
833
            HttpServletRequest request, HttpServletResponse response)
834
    {
835

    
836
        String qformat = "xml";
837
        if(params.get("qformat") != null){
838
            qformat = ((String[]) params.get("qformat"))[0];
839
        }
840

    
841
        // close the connection
842
        HttpSession sess = request.getSession(false);
843
        logMetacat.info("After get session in logout request");
844
        if (sess != null) {
845
            logMetacat.info("The session id " + sess.getId()
846
                    + " will be invalidate in logout action");
847
            logMetacat.warn("The session contains user "
848
                    + sess.getAttribute("username")
849
                    + " will be invalidate in logout action");
850
            sess.invalidate();
851
        }
852

    
853
        // produce output
854
        StringBuffer output = new StringBuffer();
855
        output.append("<?xml version=\"1.0\"?>");
856
        output.append("<logout>");
857
        output.append("User logged out");
858
        output.append("</logout>");
859

    
860
        //format and transform the output
861
        if (qformat.equals("xml")) {
862
            response.setContentType("text/xml");
863
            out.println(output.toString());
864
        } else {
865
            try {
866
                DBTransform trans = new DBTransform();
867
                response.setContentType("text/html");
868
                trans.transformXMLDocument(output.toString(),
869
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
870
                        out, null);
871
            } catch (Exception e) {
872
                logMetacat.error(
873
                        "Error in MetaCatServlet.handleLogoutAction"
874
                                + e.getMessage());
875
            }
876
        }
877
    }
878

    
879
    // END OF LOGIN & LOGOUT SECTION
880

    
881
    // SQUERY & QUERY SECTION
882
    /**
883
     * Retreive the squery xml, execute it and display it
884
     *
885
     * @param out the output stream to the client
886
     * @param params the Hashtable of parameters that should be included in the
887
     *            squery.
888
     * @param response the response object linked to the client
889
     * @param conn the database connection
890
     */
891
    private void handleSQuery(PrintWriter out, Hashtable params,
892
            HttpServletResponse response, String user, String[] groups,
893
            String sessionid)
894
    {
895
        double startTime = System.currentTimeMillis() / 1000;
896
        DBQuery queryobj = new DBQuery(saxparser);
897
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
898
        double outPutTime = System.currentTimeMillis() / 1000;
899
        logMetacat.warn("Total search time for action 'squery': "
900
                + (outPutTime - startTime));
901

    
902
    }
903

    
904
    /**
905
     * Create the xml query, execute it and display the results.
906
     *
907
     * @param out the output stream to the client
908
     * @param params the Hashtable of parameters that should be included in the
909
     *            squery.
910
     * @param response the response object linked to the client
911
     */
912
    private void handleQuery(PrintWriter out, Hashtable params,
913
            HttpServletResponse response, String user, String[] groups,
914
            String sessionid)
915
    {
916
        //create the query and run it
917
        String xmlquery = DBQuery.createSQuery(params);
918
        String[] queryArray = new String[1];
919
        queryArray[0] = xmlquery;
920
        params.put("query", queryArray);
921
        double startTime = System.currentTimeMillis() / 1000;
922
        DBQuery queryobj = new DBQuery(saxparser);
923
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
924
        double outPutTime = System.currentTimeMillis() / 1000;
925
        logMetacat.warn("Total search time for action 'query': "
926
                + (outPutTime - startTime));
927

    
928
        //handleSQuery(out, params, response,user, groups, sessionid);
929
    }
930

    
931
    // END OF SQUERY & QUERY SECTION
932

    
933
    //Exoport section
934
    /**
935
     * Handle the "export" request of data package from Metacat in zip format
936
     *
937
     * @param params the Hashtable of HTTP request parameters
938
     * @param response the HTTP response object linked to the client
939
     * @param user the username sent the request
940
     * @param groups the user's groupnames
941
     */
942
    private void handleExportAction(Hashtable params,
943
            HttpServletResponse response,
944
            String user, String[] groups, String passWord)
945
    {
946
        // Output stream
947
        ServletOutputStream out = null;
948
        // Zip output stream
949
        ZipOutputStream zOut = null;
950
        DBQuery queryObj = null;
951

    
952
        String[] docs = new String[10];
953
        String docId = "";
954

    
955
        try {
956
            // read the params
957
            if (params.containsKey("docid")) {
958
                docs = (String[]) params.get("docid");
959
            }
960
            // Create a DBuery to handle export
961
            queryObj = new DBQuery(saxparser);
962
            // Get the docid
963
            docId = docs[0];
964
            // Make sure the client specify docid
965
            if (docId == null || docId.equals("")) {
966
                response.setContentType("text/xml"); //MIME type
967
                // Get a printwriter
968
                PrintWriter pw = response.getWriter();
969
                // Send back message
970
                pw.println("<?xml version=\"1.0\"?>");
971
                pw.println("<error>");
972
                pw.println("You didn't specify requested docid");
973
                pw.println("</error>");
974
                // Close printwriter
975
                pw.close();
976
                return;
977
            }
978
            // Get output stream
979
            out = response.getOutputStream();
980
            response.setContentType("application/zip"); //MIME type
981
            response.setHeader("Content-Disposition", 
982
            		"attachment; filename=" 
983
            		+ docId + ".zip"); // Set the name of the zip file
984
            		
985
            zOut = new ZipOutputStream(out);
986
            zOut = queryObj
987
                    .getZippedPackage(docId, out, user, groups, passWord);
988
            zOut.finish(); //terminate the zip file
989
            zOut.close(); //close the zip stream
990

    
991
        } catch (Exception e) {
992
            try {
993
                response.setContentType("text/xml"); //MIME type
994
                // Send error message back
995
                if (out != null) {
996
                    PrintWriter pw = new PrintWriter(out);
997
                    pw.println("<?xml version=\"1.0\"?>");
998
                    pw.println("<error>");
999
                    pw.println(e.getMessage());
1000
                    pw.println("</error>");
1001
                    // Close printwriter
1002
                    pw.close();
1003
                    // Close output stream
1004
                    out.close();
1005
                }
1006
                // Close zip output stream
1007
                if (zOut != null) {
1008
                    zOut.close();
1009
                }
1010
            } catch (IOException ioe) {
1011
                logMetacat.error("Problem with the servlet output "
1012
                        + "in MetacatServlet.handleExportAction: "
1013
                        + ioe.getMessage());
1014
            }
1015

    
1016
            logMetacat.error(
1017
                    "Error in MetacatServlet.handleExportAction: "
1018
                            + e.getMessage());
1019
            e.printStackTrace(System.out);
1020

    
1021
        }
1022

    
1023
    }
1024

    
1025
    /**
1026
     * In eml2 document, the xml can have inline data and data was stripped off
1027
     * and store in file system. This action can be used to read inline data
1028
     * only
1029
     *
1030
     * @param params the Hashtable of HTTP request parameters
1031
     * @param response the HTTP response object linked to the client
1032
     * @param user the username sent the request
1033
     * @param groups the user's groupnames
1034
     */
1035
    private void handleReadInlineDataAction(Hashtable params,
1036
            HttpServletRequest request, HttpServletResponse response,
1037
            String user, String passWord, String[] groups)
1038
    {
1039
        String[] docs = new String[10];
1040
        String inlineDataId = null;
1041
        String docId = "";
1042
        ServletOutputStream out = null;
1043

    
1044
        try {
1045
            // read the params
1046
            if (params.containsKey("inlinedataid")) {
1047
                docs = (String[]) params.get("inlinedataid");
1048
            }
1049
            // Get the docid
1050
            inlineDataId = docs[0];
1051
            // Make sure the client specify docid
1052
            if (inlineDataId == null || inlineDataId.equals("")) {
1053
                throw new Exception("You didn't specify requested inlinedataid"); }
1054

    
1055
            // check for permission
1056
            docId = MetaCatUtil
1057
                    .getDocIdWithoutRevFromInlineDataID(inlineDataId);
1058
            PermissionController controller = new PermissionController(docId);
1059
            // check top level read permission
1060
            if (!controller.hasPermission(user, groups,
1061
                    AccessControlInterface.READSTRING))
1062
            {
1063
                throw new Exception("User " + user
1064
                        + " doesn't have permission " + " to read document "
1065
                        + docId);
1066
            }
1067
            else
1068
            {
1069
              //check data access level
1070
              try
1071
              {
1072
                Hashtable unReadableInlineDataList =
1073
                    PermissionController.getUnReadableInlineDataIdList(docId,
1074
                    user, groups, false);
1075
                if (unReadableInlineDataList.containsValue(
1076
                          MetaCatUtil.getInlineDataIdWithoutRev(inlineDataId)))
1077
                {
1078
                  throw new Exception("User " + user
1079
                       + " doesn't have permission " + " to read inlinedata "
1080
                       + inlineDataId);
1081

    
1082
                }//if
1083
              }//try
1084
              catch (Exception e)
1085
              {
1086
                throw e;
1087
              }//catch
1088
            }//else
1089

    
1090
            // Get output stream
1091
            out = response.getOutputStream();
1092
            // read the inline data from the file
1093
            String inlinePath = MetaCatUtil.getOption("inlinedatafilepath");
1094
            File lineData = new File(inlinePath, inlineDataId);
1095
            FileInputStream input = new FileInputStream(lineData);
1096
            byte[] buffer = new byte[4 * 1024];
1097
            int bytes = input.read(buffer);
1098
            while (bytes != -1) {
1099
                out.write(buffer, 0, bytes);
1100
                bytes = input.read(buffer);
1101
            }
1102
            out.close();
1103

    
1104
            EventLog.getInstance().log(request.getRemoteAddr(), user,
1105
                    inlineDataId, "readinlinedata");
1106
        } catch (Exception e) {
1107
            try {
1108
                PrintWriter pw = null;
1109
                // Send error message back
1110
                if (out != null) {
1111
                    pw = new PrintWriter(out);
1112
                } else {
1113
                    pw = response.getWriter();
1114
                }
1115
                pw.println("<?xml version=\"1.0\"?>");
1116
                pw.println("<error>");
1117
                pw.println(e.getMessage());
1118
                pw.println("</error>");
1119
                // Close printwriter
1120
                pw.close();
1121
                // Close output stream if out is not null
1122
                if (out != null) {
1123
                    out.close();
1124
                }
1125
            } catch (IOException ioe) {
1126
                logMetacat.error("Problem with the servlet output "
1127
                        + "in MetacatServlet.handleExportAction: "
1128
                        + ioe.getMessage());
1129
            }
1130
            logMetacat.error(
1131
                    "Error in MetacatServlet.handleReadInlineDataAction: "
1132
                            + e.getMessage());
1133
        }
1134
    }
1135

    
1136
    /*
1137
     * Get the nodeid from xml_nodes for the inlinedataid
1138
     */
1139
    private long getInlineDataNodeId(String inLineDataId, String docId)
1140
            throws SQLException
1141
    {
1142
        long nodeId = 0;
1143
        String INLINE = "inline";
1144
        boolean hasRow;
1145
        PreparedStatement pStmt = null;
1146
        DBConnection conn = null;
1147
        int serialNumber = -1;
1148
        String sql = "SELECT nodeid FROM xml_nodes WHERE docid=? AND nodedata=? "
1149
                + "AND nodetype='TEXT' AND parentnodeid IN "
1150
                + "(SELECT nodeid FROM xml_nodes WHERE docid=? AND "
1151
                + "nodetype='ELEMENT' AND nodename='" + INLINE + "')";
1152

    
1153
        try {
1154
            //check out DBConnection
1155
            conn = DBConnectionPool
1156
                    .getDBConnection("AccessControlList.isAllowFirst");
1157
            serialNumber = conn.getCheckOutSerialNumber();
1158

    
1159
            pStmt = conn.prepareStatement(sql);
1160
            //bind value
1161
            pStmt.setString(1, docId);//docid
1162
            pStmt.setString(2, inLineDataId);//inlinedataid
1163
            pStmt.setString(3, docId);
1164
            // excute query
1165
            pStmt.execute();
1166
            ResultSet rs = pStmt.getResultSet();
1167
            hasRow = rs.next();
1168
            // get result
1169
            if (hasRow) {
1170
                nodeId = rs.getLong(1);
1171
            }//if
1172

    
1173
        } catch (SQLException e) {
1174
            throw e;
1175
        } finally {
1176
            try {
1177
                pStmt.close();
1178
            } finally {
1179
                DBConnectionPool.returnDBConnection(conn, serialNumber);
1180
            }
1181
        }
1182
        logMetacat.info("The nodeid for inlinedataid " + inLineDataId
1183
                + " is: " + nodeId);
1184
        return nodeId;
1185
    }
1186

    
1187
    /**
1188
     * Handle the "read" request of metadata/data files from Metacat or any
1189
     * files from Internet; transformed metadata XML document into HTML
1190
     * presentation if requested; zip files when more than one were requested.
1191
     *
1192
     * @param params the Hashtable of HTTP request parameters
1193
     * @param request the HTTP request object linked to the client
1194
     * @param response the HTTP response object linked to the client
1195
     * @param user the username sent the request
1196
     * @param groups the user's groupnames
1197
     */
1198
    private void handleReadAction(Hashtable params, HttpServletRequest request,
1199
            HttpServletResponse response, String user, String passWord,
1200
            String[] groups)
1201
    {
1202
        ServletOutputStream out = null;
1203
        ZipOutputStream zout = null;
1204
        PrintWriter pw = null;
1205
        boolean zip = false;
1206
        boolean withInlineData = true;
1207

    
1208
        try {
1209
            String[] docs = new String[0];
1210
            String docid = "";
1211
            String qformat = "";
1212
            String abstrpath = null;
1213

    
1214
            // read the params
1215
            if (params.containsKey("docid")) {
1216
                docs = (String[]) params.get("docid");
1217
            }
1218
            if (params.containsKey("qformat")) {
1219
                qformat = ((String[]) params.get("qformat"))[0];
1220
            }
1221
            // the param for only metadata (eml)
1222
            // we don't support read a eml document without inline data now.
1223
            /*if (params.containsKey("inlinedata")) {
1224

    
1225
                String inlineData = ((String[]) params.get("inlinedata"))[0];
1226
                if (inlineData.equalsIgnoreCase("false")) {
1227
                    withInlineData = false;
1228
                }
1229
            }*/
1230
            if ((docs.length > 1) || qformat.equals("zip")) {
1231
                zip = true;
1232
                out = response.getOutputStream();
1233
                response.setContentType("application/zip"); //MIME type
1234
                zout = new ZipOutputStream(out);
1235
            }
1236
            // go through the list of docs to read
1237
            for (int i = 0; i < docs.length; i++) {
1238
                try {
1239

    
1240
                    URL murl = new URL(docs[i]);
1241
                    Hashtable murlQueryStr = MetaCatUtil.parseQuery(
1242
                            murl.getQuery());
1243
                    // case docid="http://.../?docid=aaa"
1244
                    // or docid="metacat://.../?docid=bbb"
1245
                    if (murlQueryStr.containsKey("docid")) {
1246
                        // get only docid, eliminate the rest
1247
                        docid = (String) murlQueryStr.get("docid");
1248
                        if (zip) {
1249
                            addDocToZip(request, docid, zout, user, groups);
1250
                        } else {
1251
                            readFromMetacat(request, response, docid, qformat,
1252
                                    abstrpath, user, groups, zip, zout,
1253
                                    withInlineData, params);
1254
                        }
1255

    
1256
                        // case docid="http://.../filename"
1257
                    } else {
1258
                        docid = docs[i];
1259
                        if (zip) {
1260
                            addDocToZip(request, docid, zout, user, groups);
1261
                        } else {
1262
                            readFromURLConnection(response, docid);
1263
                        }
1264
                    }
1265

    
1266
                } catch (MalformedURLException mue) {
1267
                    docid = docs[i];
1268
                    if (zip) {
1269
                        addDocToZip(request, docid, zout, user, groups);
1270
                    } else {
1271
                        readFromMetacat(request, response, docid, qformat,
1272
                                abstrpath, user, groups, zip, zout,
1273
                                withInlineData, params);
1274
                    }
1275
                }
1276
            }
1277

    
1278
            if (zip) {
1279
                zout.finish(); //terminate the zip file
1280
                zout.close(); //close the zip stream
1281
            }
1282

    
1283
        } catch (McdbDocNotFoundException notFoundE) {
1284
            // To handle doc not found exception
1285
            // the docid which didn't be found
1286
            String notFoundDocId = notFoundE.getUnfoundDocId();
1287
            String notFoundRevision = notFoundE.getUnfoundRevision();
1288
            logMetacat.warn("Missed id: " + notFoundDocId);
1289
            logMetacat.warn("Missed rev: " + notFoundRevision);
1290
            try {
1291
                // read docid from remote server
1292
                readFromRemoteMetaCat(response, notFoundDocId,
1293
                        notFoundRevision, user, passWord, out, zip, zout);
1294
                // Close zout outputstream
1295
                if (zout != null) {
1296
                    zout.close();
1297
                }
1298
                // close output stream
1299
                if (out != null) {
1300
                    out.close();
1301
                }
1302

    
1303
            } catch (Exception exc) {
1304
                logMetacat.error(
1305
                        "Erorr in MetacatServlet.hanldReadAction: "
1306
                                + exc.getMessage());
1307
                try {
1308
                    if (out != null) {
1309
                        response.setContentType("text/xml");
1310
                        // Send back error message by printWriter
1311
                        pw = new PrintWriter(out);
1312
                        pw.println("<?xml version=\"1.0\"?>");
1313
                        pw.println("<error>");
1314
                        pw.println(notFoundE.getMessage());
1315
                        pw.println("</error>");
1316
                        pw.close();
1317
                        out.close();
1318

    
1319
                    } else {
1320
                        response.setContentType("text/xml"); //MIME type
1321
                        // Send back error message if out = null
1322
                        if (pw == null) {
1323
                            // If pw is null, open the respnose
1324
                            pw = response.getWriter();
1325
                        }
1326
                        pw.println("<?xml version=\"1.0\"?>");
1327
                        pw.println("<error>");
1328
                        pw.println(notFoundE.getMessage());
1329
                        pw.println("</error>");
1330
                        pw.close();
1331
                    }
1332
                    // close zout
1333
                    if (zout != null) {
1334
                        zout.close();
1335
                    }
1336
                } catch (IOException ie) {
1337
                    logMetacat.error("Problem with the servlet output "
1338
                            + "in MetacatServlet.handleReadAction: "
1339
                            + ie.getMessage());
1340
                }
1341
            }
1342
        } catch (Exception e) {
1343
            try {
1344

    
1345
                if (out != null) {
1346
                    response.setContentType("text/xml"); //MIME type
1347
                    pw = new PrintWriter(out);
1348
                    pw.println("<?xml version=\"1.0\"?>");
1349
                    pw.println("<error>");
1350
                    pw.println(e.getMessage());
1351
                    pw.println("</error>");
1352
                    pw.close();
1353
                    out.close();
1354
                } else {
1355
                    response.setContentType("text/xml"); //MIME type
1356
                    // Send back error message if out = null
1357
                    if (pw == null) {
1358
                        pw = response.getWriter();
1359
                    }
1360
                    pw.println("<?xml version=\"1.0\"?>");
1361
                    pw.println("<error>");
1362
                    pw.println(e.getMessage());
1363
                    pw.println("</error>");
1364
                    pw.close();
1365

    
1366
                }
1367
                // Close zip output stream
1368
                if (zout != null) {
1369
                    zout.close();
1370
                }
1371

    
1372
            } catch (IOException ioe) {
1373
                logMetacat.error("Problem with the servlet output "
1374
                        + "in MetacatServlet.handleReadAction: "
1375
                        + ioe.getMessage());
1376
                ioe.printStackTrace(System.out);
1377

    
1378
            }
1379

    
1380
            logMetacat.error(
1381
                    "Error in MetacatServlet.handleReadAction: "
1382
                            + e.getMessage());
1383
            //e.printStackTrace(System.out);
1384
        }
1385
    }
1386

    
1387
    /** read metadata or data from Metacat
1388
     */
1389
    private void readFromMetacat(HttpServletRequest request,
1390
            HttpServletResponse response, String docid, String qformat,
1391
            String abstrpath, String user, String[] groups, boolean zip,
1392
            ZipOutputStream zout, boolean withInlineData, Hashtable params)
1393
            throws ClassNotFoundException, IOException, SQLException,
1394
            McdbException, Exception
1395
    {
1396

    
1397
        try {
1398
            
1399
            // here is hack for handle docid=john.10(in order to tell mike.jim.10.1
1400
            // mike.jim.10, we require to provide entire docid with rev). But
1401
            // some old client they only provide docid without rev, so we need
1402
            // to handle this suituation. First we will check how many
1403
            // seperator here, if only one, we will append the rev in xml_documents
1404
            // to the id.
1405
            docid = appendRev(docid);
1406
         
1407
            DocumentImpl doc = new DocumentImpl(docid);
1408

    
1409
            //check the permission for read
1410
            if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1411
                Exception e = new Exception("User " + user
1412
                        + " does not have permission"
1413
                        + " to read the document with the docid " + docid);
1414

    
1415
                throw e;
1416
            }
1417

    
1418
            if (doc.getRootNodeID() == 0) {
1419
                // this is data file
1420
                String filepath = MetaCatUtil.getOption("datafilepath");
1421
                if (!filepath.endsWith("/")) {
1422
                    filepath += "/";
1423
                }
1424
                String filename = filepath + docid;
1425
                FileInputStream fin = null;
1426
                fin = new FileInputStream(filename);
1427

    
1428
                //MIME type
1429
                String contentType = getServletContext().getMimeType(filename);
1430
                if (contentType == null) {
1431
                    ContentTypeProvider provider = new ContentTypeProvider(
1432
                            docid);
1433
                    contentType = provider.getContentType();
1434
                    logMetacat.warn("Final contenttype is: "
1435
                            + contentType);
1436
                }
1437

    
1438
                response.setContentType(contentType);
1439
                // if we decide to use "application/octet-stream" for all data
1440
                // returns
1441
                // response.setContentType("application/octet-stream");
1442

    
1443
                try {
1444

    
1445
                    ServletOutputStream out = response.getOutputStream();
1446
                    byte[] buf = new byte[4 * 1024]; // 4K buffer
1447
                    int b = fin.read(buf);
1448
                    while (b != -1) {
1449
                        out.write(buf, 0, b);
1450
                        b = fin.read(buf);
1451
                    }
1452
                } finally {
1453
                    if (fin != null) fin.close();
1454
                }
1455

    
1456
            } else {
1457
                // this is metadata doc
1458
                if (qformat.equals("xml") || qformat.equals("")) {
1459
                    // if equals "", that means no qformat is specified. hence
1460
                    // by default the document should be returned in xml format
1461
                    // set content type first
1462
                    response.setContentType("text/xml"); //MIME type
1463
                    PrintWriter out = response.getWriter();
1464
                    doc.toXml(out, user, groups, withInlineData);
1465
                } else {
1466
                    response.setContentType("text/html"); //MIME type
1467
                    PrintWriter out = response.getWriter();
1468

    
1469
                    // Look up the document type
1470
                    String doctype = doc.getDoctype();
1471
                    // Transform the document to the new doctype
1472
                    DBTransform dbt = new DBTransform();
1473
                    dbt.transformXMLDocument(doc.toString(user, groups,
1474
                            withInlineData), doctype, "-//W3C//HTML//EN",
1475
                            qformat, out, params);
1476
                }
1477

    
1478
            }
1479
            EventLog.getInstance().log(request.getRemoteAddr(), user,
1480
                    docid, "read");
1481
        } catch (Exception except) {
1482
            throw except;
1483
        }
1484
    }
1485

    
1486
    /**
1487
     * read data from URLConnection
1488
     */
1489
    private void readFromURLConnection(HttpServletResponse response,
1490
            String docid) throws IOException, MalformedURLException
1491
    {
1492
        ServletOutputStream out = response.getOutputStream();
1493
        String contentType = getServletContext().getMimeType(docid); //MIME
1494
                                                                     // type
1495
        if (contentType == null) {
1496
            if (docid.endsWith(".xml")) {
1497
                contentType = "text/xml";
1498
            } else if (docid.endsWith(".css")) {
1499
                contentType = "text/css";
1500
            } else if (docid.endsWith(".dtd")) {
1501
                contentType = "text/plain";
1502
            } else if (docid.endsWith(".xsd")) {
1503
                contentType = "text/xml";
1504
            } else if (docid.endsWith("/")) {
1505
                contentType = "text/html";
1506
            } else {
1507
                File f = new File(docid);
1508
                if (f.isDirectory()) {
1509
                    contentType = "text/html";
1510
                } else {
1511
                    contentType = "application/octet-stream";
1512
                }
1513
            }
1514
        }
1515
        response.setContentType(contentType);
1516
        // if we decide to use "application/octet-stream" for all data returns
1517
        // response.setContentType("application/octet-stream");
1518

    
1519
        // this is http url
1520
        URL url = new URL(docid);
1521
        BufferedInputStream bis = null;
1522
        try {
1523
            bis = new BufferedInputStream(url.openStream());
1524
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1525
            int b = bis.read(buf);
1526
            while (b != -1) {
1527
                out.write(buf, 0, b);
1528
                b = bis.read(buf);
1529
            }
1530
        } finally {
1531
            if (bis != null) bis.close();
1532
        }
1533

    
1534
    }
1535

    
1536
    /**
1537
     * read file/doc and write to ZipOutputStream
1538
     *
1539
     * @param docid
1540
     * @param zout
1541
     * @param user
1542
     * @param groups
1543
     * @throws ClassNotFoundException
1544
     * @throws IOException
1545
     * @throws SQLException
1546
     * @throws McdbException
1547
     * @throws Exception
1548
     */
1549
    private void addDocToZip(HttpServletRequest request, String docid,
1550
            ZipOutputStream zout, String user, String[] groups) throws
1551
            ClassNotFoundException, IOException, SQLException, McdbException,
1552
            Exception
1553
    {
1554
        byte[] bytestring = null;
1555
        ZipEntry zentry = null;
1556

    
1557
        try {
1558
            URL url = new URL(docid);
1559

    
1560
            // this http url; read from URLConnection; add to zip
1561
            zentry = new ZipEntry(docid);
1562
            zout.putNextEntry(zentry);
1563
            BufferedInputStream bis = null;
1564
            try {
1565
                bis = new BufferedInputStream(url.openStream());
1566
                byte[] buf = new byte[4 * 1024]; // 4K buffer
1567
                int b = bis.read(buf);
1568
                while (b != -1) {
1569
                    zout.write(buf, 0, b);
1570
                    b = bis.read(buf);
1571
                }
1572
            } finally {
1573
                if (bis != null) bis.close();
1574
            }
1575
            zout.closeEntry();
1576

    
1577
        } catch (MalformedURLException mue) {
1578

    
1579
            // this is metacat doc (data file or metadata doc)
1580
            try {
1581
                DocumentImpl doc = new DocumentImpl(docid);
1582

    
1583
                //check the permission for read
1584
                if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1585
                    Exception e = new Exception("User " + user
1586
                            + " does not have "
1587
                            + "permission to read the document with the docid "
1588
                            + docid);
1589
                    throw e;
1590
                }
1591

    
1592
                if (doc.getRootNodeID() == 0) {
1593
                    // this is data file; add file to zip
1594
                    String filepath = MetaCatUtil.getOption("datafilepath");
1595
                    if (!filepath.endsWith("/")) {
1596
                        filepath += "/";
1597
                    }
1598
                    String filename = filepath + docid;
1599
                    FileInputStream fin = null;
1600
                    fin = new FileInputStream(filename);
1601
                    try {
1602

    
1603
                        zentry = new ZipEntry(docid);
1604
                        zout.putNextEntry(zentry);
1605
                        byte[] buf = new byte[4 * 1024]; // 4K buffer
1606
                        int b = fin.read(buf);
1607
                        while (b != -1) {
1608
                            zout.write(buf, 0, b);
1609
                            b = fin.read(buf);
1610
                        }
1611
                    } finally {
1612
                        if (fin != null) fin.close();
1613
                    }
1614
                    zout.closeEntry();
1615

    
1616
                } else {
1617
                    // this is metadata doc; add doc to zip
1618
                    bytestring = doc.toString().getBytes();
1619
                    zentry = new ZipEntry(docid + ".xml");
1620
                    zentry.setSize(bytestring.length);
1621
                    zout.putNextEntry(zentry);
1622
                    zout.write(bytestring, 0, bytestring.length);
1623
                    zout.closeEntry();
1624
                }
1625
                EventLog.getInstance().log(request.getRemoteAddr(), user,
1626
                        docid, "read");
1627
            } catch (Exception except) {
1628
                throw except;
1629
            }
1630
        }
1631
    }
1632

    
1633
    /**
1634
     * If metacat couldn't find a data file or document locally, it will read
1635
     * this docid from its home server. This is for the replication feature
1636
     */
1637
    private void readFromRemoteMetaCat(HttpServletResponse response,
1638
            String docid, String rev, String user, String password,
1639
            ServletOutputStream out, boolean zip, ZipOutputStream zout)
1640
            throws Exception
1641
    {
1642
        // Create a object of RemoteDocument, "" is for zipEntryPath
1643
        RemoteDocument remoteDoc = new RemoteDocument(docid, rev, user,
1644
                password, "");
1645
        String docType = remoteDoc.getDocType();
1646
        // Only read data file
1647
        if (docType.equals("BIN")) {
1648
            // If it is zip format
1649
            if (zip) {
1650
                remoteDoc.readDocumentFromRemoteServerByZip(zout);
1651
            } else {
1652
                if (out == null) {
1653
                    out = response.getOutputStream();
1654
                }
1655
                response.setContentType("application/octet-stream");
1656
                remoteDoc.readDocumentFromRemoteServer(out);
1657
            }
1658
        } else {
1659
            throw new Exception("Docid: " + docid + "." + rev
1660
                    + " couldn't find");
1661
        }
1662
    }
1663

    
1664
    /**
1665
     * Handle the database putdocument request and write an XML document to the
1666
     * database connection
1667
     */
1668
    private void handleInsertOrUpdateAction(HttpServletRequest request,
1669
            HttpServletResponse response, PrintWriter out, Hashtable params,
1670
            String user, String[] groups)
1671
    {
1672
        DBConnection dbConn = null;
1673
        int serialNumber = -1;
1674

    
1675
        if(params.get("docid") == null){
1676
            out.println("<?xml version=\"1.0\"?>");
1677
            out.println("<error>");
1678
            out.println("Docid not specified");
1679
            out.println("</error>");
1680
            logMetacat.error("Docid not specified");
1681
            return;
1682
        }
1683
        
1684
        if(!MetaCatUtil.canInsertOrUpdate(user, groups)){
1685
        	out.println("<?xml version=\"1.0\"?>");
1686
            out.println("<error>");
1687
            out.println("User '" + user + "' not allowed to insert and update");
1688
            out.println("</error>");
1689
            logMetacat.error("User '" + user + "' not allowed to insert and update");
1690
            return;
1691
        }
1692

    
1693
        try {
1694
            // Get the document indicated
1695
            String[] doctext = (String[]) params.get("doctext");
1696
            String pub = null;
1697
            if (params.containsKey("public")) {
1698
                pub = ((String[]) params.get("public"))[0];
1699
            }
1700

    
1701
            StringReader dtd = null;
1702
            if (params.containsKey("dtdtext")) {
1703
                String[] dtdtext = (String[]) params.get("dtdtext");
1704
                try {
1705
                    if (!dtdtext[0].equals("")) {
1706
                        dtd = new StringReader(dtdtext[0]);
1707
                    }
1708
                } catch (NullPointerException npe) {
1709
                }
1710
            }
1711

    
1712
            if(doctext == null){
1713
                out.println("<?xml version=\"1.0\"?>");
1714
                out.println("<error>");
1715
                out.println("Document text not submitted");
1716
                out.println("</error>");
1717
                return;
1718
            }
1719

    
1720
            StringReader xml = new StringReader(doctext[0]);
1721
            boolean validate = false;
1722
            DocumentImplWrapper documentWrapper = null;
1723
            try {
1724
                // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ...
1725
                // >
1726
                // in order to decide whether to use validation parser
1727
                validate = needDTDValidation(xml);
1728
                if (validate) {
1729
                    // set a dtd base validation parser
1730
                    String rule = DocumentImpl.DTD;
1731
                    documentWrapper = new DocumentImplWrapper(rule, validate);
1732
                } else {
1733

    
1734
                    String namespace = findNamespace(xml);
1735
                    
1736
                	if (namespace != null) {
1737
                		if (namespace.compareTo(DocumentImpl.EML2_0_0NAMESPACE) == 0
1738
                				|| namespace.compareTo(
1739
                				DocumentImpl.EML2_0_1NAMESPACE) == 0) {
1740
                			// set eml2 base	 validation parser
1741
                			String rule = DocumentImpl.EML200;
1742
                			// using emlparser to check id validation
1743
                			EMLParser parser = new EMLParser(doctext[0]);
1744
                			documentWrapper = new DocumentImplWrapper(rule, true);
1745
                		} else if (namespace.compareTo(
1746
                                DocumentImpl.EML2_1_0NAMESPACE) == 0) {
1747
                			// set eml2 base validation parser
1748
                			String rule = DocumentImpl.EML210;
1749
                			// using emlparser to check id validation
1750
                			EMLParser parser = new EMLParser(doctext[0]);
1751
                			documentWrapper = new DocumentImplWrapper(rule, true);
1752
                		} else {
1753
                			// set schema base validation parser
1754
                			String rule = DocumentImpl.SCHEMA;
1755
                			documentWrapper = new DocumentImplWrapper(rule, true);
1756
                		}
1757
                	} else {
1758
                		documentWrapper = new DocumentImplWrapper("", false);
1759
                	}
1760
                }
1761

    
1762
                String[] action = (String[]) params.get("action");
1763
                String[] docid = (String[]) params.get("docid");
1764
                String newdocid = null;
1765

    
1766
                String doAction = null;
1767
                if (action[0].equals("insert")) {
1768
                    doAction = "INSERT";
1769
                } else if (action[0].equals("update")) {
1770
                    doAction = "UPDATE";
1771
                }
1772

    
1773
                try {
1774
                    // get a connection from the pool
1775
                    dbConn = DBConnectionPool
1776
                            .getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1777
                    serialNumber = dbConn.getCheckOutSerialNumber();
1778

    
1779
                    // write the document to the database
1780
                    try {
1781
                        String accNumber = docid[0];
1782
                        logMetacat.warn("" + doAction + " "
1783
                                + accNumber + "...");
1784
                        if (accNumber.equals("")) {
1785
                            accNumber = null;
1786
                        }
1787
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1788
                                doAction, accNumber, user, groups);
1789
                        EventLog.getInstance().log(request.getRemoteAddr(),
1790
                                user, accNumber, action[0]);
1791
                    } catch (NullPointerException npe) {
1792
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1793
                                doAction, null, user, groups);
1794
                        EventLog.getInstance().log(request.getRemoteAddr(),
1795
                                user, "", action[0]);
1796
                    }
1797
                }
1798
                finally {
1799
                    // Return db connection
1800
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1801
                }
1802

    
1803
                // set content type and other response header fields first
1804
                //response.setContentType("text/xml");
1805
                out.println("<?xml version=\"1.0\"?>");
1806
                out.println("<success>");
1807
                out.println("<docid>" + newdocid + "</docid>");
1808
                out.println("</success>");
1809

    
1810
            } catch (NullPointerException npe) {
1811
                //response.setContentType("text/xml");
1812
                out.println("<?xml version=\"1.0\"?>");
1813
                out.println("<error>");
1814
                out.println(npe.getMessage());
1815
                out.println("</error>");
1816
                logMetacat.warn("Error in writing eml document to the database" + npe.getMessage());
1817
                npe.printStackTrace();
1818
            }
1819
        } catch (Exception e) {
1820
            //response.setContentType("text/xml");
1821
            out.println("<?xml version=\"1.0\"?>");
1822
            out.println("<error>");
1823
            out.println(e.getMessage());
1824
            out.println("</error>");
1825
            logMetacat.warn("Error in writing eml document to the database" + e.getMessage());
1826
            e.printStackTrace();
1827
        }
1828
    }
1829

    
1830
    /**
1831
     * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > in
1832
     * order to decide whether to use validation parser
1833
     */
1834
    private static boolean needDTDValidation(StringReader xmlreader)
1835
            throws IOException
1836
    {
1837

    
1838
        StringBuffer cbuff = new StringBuffer();
1839
        java.util.Stack st = new java.util.Stack();
1840
        boolean validate = false;
1841
        int c;
1842
        int inx;
1843

    
1844
        // read from the stream until find the keywords
1845
        while ((st.empty() || st.size() < 4) && ((c = xmlreader.read()) != -1)) {
1846
            cbuff.append((char) c);
1847

    
1848
            // "<!DOCTYPE" keyword is found; put it in the stack
1849
            if ((inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1) {
1850
                cbuff = new StringBuffer();
1851
                st.push("<!DOCTYPE");
1852
            }
1853
            // "PUBLIC" keyword is found; put it in the stack
1854
            if ((inx = cbuff.toString().indexOf("PUBLIC")) != -1) {
1855
                cbuff = new StringBuffer();
1856
                st.push("PUBLIC");
1857
            }
1858
            // "SYSTEM" keyword is found; put it in the stack
1859
            if ((inx = cbuff.toString().indexOf("SYSTEM")) != -1) {
1860
                cbuff = new StringBuffer();
1861
                st.push("SYSTEM");
1862
            }
1863
            // ">" character is found; put it in the stack
1864
            // ">" is found twice: fisrt from <?xml ...?>
1865
            // and second from <!DOCTYPE ... >
1866
            if ((inx = cbuff.toString().indexOf(">")) != -1) {
1867
                cbuff = new StringBuffer();
1868
                st.push(">");
1869
            }
1870
        }
1871

    
1872
        // close the stream
1873
        xmlreader.reset();
1874

    
1875
        // check the stack whether it contains the keywords:
1876
        // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1877
        if (st.size() == 4) {
1878
            if (((String) st.pop()).equals(">")
1879
                    && (((String) st.peek()).equals("PUBLIC") | ((String) st
1880
                            .pop()).equals("SYSTEM"))
1881
                    && ((String) st.pop()).equals("<!DOCTYPE")) {
1882
                validate = true;
1883
            }
1884
        }
1885

    
1886
        logMetacat.warn("Validation for dtd is " + validate);
1887
        return validate;
1888
    }
1889

    
1890
    // END OF INSERT/UPDATE SECTION
1891

    
1892
    /* check if the xml string contains key words to specify schema loocation */
1893
    private String findNamespace(StringReader xml) throws IOException
1894
    {
1895
        String namespace = null;
1896

    
1897
        String eml2_0_0NameSpace = DocumentImpl.EML2_0_0NAMESPACE;
1898
        String eml2_0_1NameSpace = DocumentImpl.EML2_0_1NAMESPACE;
1899
        String eml2_1_0NameSpace = DocumentImpl.EML2_1_0NAMESPACE;
1900

    
1901
        if (xml == null) {
1902
            logMetacat.warn("Validation for schema is "
1903
                    + namespace);
1904
            return namespace;
1905
        }
1906
        String targetLine = getSchemaLine(xml);
1907

    
1908
        if (targetLine != null) {
1909

    
1910
        	// find if the root element has prefix
1911
        	String prefix = getPrefix(targetLine);
1912
        	logMetacat.info("prefix is:" + prefix);
1913
        	int startIndex = 0;
1914
        	
1915
        	
1916
        	if(prefix != null)
1917
        	{
1918
        		// if prefix found then look for xmlns:prefix
1919
        		// element to find the ns 
1920
        		String namespaceWithPrefix = NAMESPACEKEYWORD 
1921
        					+ ":" + prefix;
1922
        		startIndex = targetLine.indexOf(namespaceWithPrefix);
1923
            	logMetacat.info("namespaceWithPrefix is:" + namespaceWithPrefix+":");
1924
            	logMetacat.info("startIndex is:" + startIndex);
1925
        		
1926
        	} else {
1927
        		// if prefix not found then look for xmlns
1928
        		// attribute to find the ns 
1929
        		startIndex = targetLine.indexOf(NAMESPACEKEYWORD);
1930
            	logMetacat.info("startIndex is:" + startIndex);
1931
        	}
1932
        		
1933
            int start = 1;
1934
            int end = 1;
1935
            String namespaceString = null;
1936
            int count = 0;
1937
            if (startIndex != -1) {
1938
                for (int i = startIndex; i < targetLine.length(); i++) {
1939
                    if (targetLine.charAt(i) == '"') {
1940
                        count++;
1941
                    }
1942
                    if (targetLine.charAt(i) == '"' && count == 1) {
1943
                        start = i;
1944
                    }
1945
                    if (targetLine.charAt(i) == '"' && count == 2) {
1946
                        end = i;
1947
                        break;
1948
                    }
1949
                }
1950
            } 
1951
            // else: xmlns not found. namespace = null will be returned
1952

    
1953
         	logMetacat.info("targetLine is " + targetLine);
1954
         	logMetacat.debug("start is " + end);
1955
         	logMetacat.debug("end is " + end);
1956
           
1957
            if(start < end){
1958
            	namespaceString = targetLine.substring(start + 1, end);
1959
            	logMetacat.info("namespaceString is " + namespaceString);
1960
            }
1961
            logMetacat.info("namespace in xml is: "
1962
                    + namespaceString);
1963
            if(namespaceString != null){
1964
            	if (namespaceString.indexOf(eml2_0_0NameSpace) != -1) {
1965
            		namespace = eml2_0_0NameSpace;
1966
            	} else if (namespaceString.indexOf(eml2_0_1NameSpace) != -1) {
1967
            		namespace = eml2_0_1NameSpace;
1968
            	} else if (namespaceString.indexOf(eml2_1_0NameSpace) != -1) {
1969
            		namespace = eml2_1_0NameSpace;
1970
            	} else {
1971
            		namespace = namespaceString;
1972
            	}
1973
            }
1974
        }
1975

    
1976
        logMetacat.warn("Validation for eml is " + namespace);
1977

    
1978
        return namespace;
1979

    
1980
    }
1981

    
1982
    private String getSchemaLine(StringReader xml) throws IOException
1983
    {
1984
        // find the line
1985
        String secondLine = null;
1986
        int count = 0;
1987
        int endIndex = 0;
1988
        int startIndex = 0;
1989
        final int TARGETNUM = 2;
1990
        StringBuffer buffer = new StringBuffer();
1991
        boolean comment = false;
1992
        char thirdPreviousCharacter = '?';
1993
        char secondPreviousCharacter = '?';
1994
        char previousCharacter = '?';
1995
        char currentCharacter = '?';
1996
        int tmp = xml.read();
1997
        while (tmp != -1) {
1998
            currentCharacter = (char)tmp;
1999
            //in a comment
2000
            if (currentCharacter == '-' && previousCharacter == '-'
2001
                    && secondPreviousCharacter == '!'
2002
                    && thirdPreviousCharacter == '<') {
2003
                comment = true;
2004
            }
2005
            //out of comment
2006
            if (comment && currentCharacter == '>' && previousCharacter == '-'
2007
                    && secondPreviousCharacter == '-') {
2008
                comment = false;
2009
            }
2010

    
2011
            //this is not comment
2012
            if (currentCharacter != '!' && previousCharacter == '<' && !comment) {
2013
                count++;
2014
            }
2015
            // get target line
2016
            if (count == TARGETNUM && currentCharacter != '>') {
2017
                buffer.append(currentCharacter);
2018
            }
2019
            if (count == TARGETNUM && currentCharacter == '>') {
2020
                break;
2021
            }
2022
            thirdPreviousCharacter = secondPreviousCharacter;
2023
            secondPreviousCharacter = previousCharacter;
2024
            previousCharacter = currentCharacter;
2025
            tmp = xml.read();
2026
        }
2027
        secondLine = buffer.toString();
2028
        logMetacat.info("the second line string is: " + secondLine);
2029
        
2030
        xml.reset();
2031
        return secondLine;
2032
    }
2033

    
2034
    private String getPrefix(String schemaLine)
2035
    {
2036
    	String prefix = null;
2037
    	String rootElement = schemaLine.substring(0, schemaLine.indexOf(" "));
2038
        logMetacat.info("rootElement:" + rootElement);
2039
        
2040
        if(rootElement.indexOf(":") > 0){
2041
        	prefix = rootElement.substring(rootElement.indexOf(":") + 1,
2042
        			rootElement.length());
2043
        } 
2044
        return prefix.trim();
2045
    }
2046

    
2047
    /**
2048
     * Handle the database delete request and delete an XML document from the
2049
     * database connection
2050
     */
2051
    private void handleDeleteAction(PrintWriter out, Hashtable params,
2052
            HttpServletRequest request, HttpServletResponse response,
2053
            String user, String[] groups)
2054
    {
2055

    
2056
        String[] docid = (String[]) params.get("docid");
2057

    
2058
        if(docid == null){
2059
          response.setContentType("text/xml");
2060
          out.println("<?xml version=\"1.0\"?>");
2061
          out.println("<error>");
2062
          out.println("Docid not specified.");
2063
          out.println("</error>");
2064
          logMetacat.error("Docid not specified for the document to be deleted.");
2065
        } else {
2066

    
2067
            // delete the document from the database
2068
            try {
2069

    
2070
                try {
2071
                    // null means notify server is null
2072
                    DocumentImpl.delete(docid[0], user, groups, null);
2073
                    EventLog.getInstance().log(request.getRemoteAddr(),
2074
                                               user, docid[0], "delete");
2075
                    response.setContentType("text/xml");
2076
                    out.println("<?xml version=\"1.0\"?>");
2077
                    out.println("<success>");
2078
                    out.println("Document deleted.");
2079
                    out.println("</success>");
2080
                    logMetacat.warn("Document deleted.");
2081
                }
2082
                catch (AccessionNumberException ane) {
2083
                    response.setContentType("text/xml");
2084
                    out.println("<?xml version=\"1.0\"?>");
2085
                    out.println("<error>");
2086
                    //out.println("Error deleting document!!!");
2087
                    out.println(ane.getMessage());
2088
                    out.println("</error>");
2089
                    logMetacat.error("Document could not be deleted: " 
2090
                    		+ ane.getMessage());
2091
                }
2092
            }
2093
            catch (Exception e) {
2094
                response.setContentType("text/xml");
2095
                out.println("<?xml version=\"1.0\"?>");
2096
                out.println("<error>");
2097
                out.println(e.getMessage());
2098
                out.println("</error>");
2099
                logMetacat.error("Document could not be deleted: " 
2100
                		+ e.getMessage());
2101
            }
2102
        }
2103
    }
2104

    
2105
    /**
2106
     * Handle the validation request and return the results to the requestor
2107
     */
2108
    private void handleValidateAction(PrintWriter out, Hashtable params)
2109
    {
2110

    
2111
        // Get the document indicated
2112
        String valtext = null;
2113
        DBConnection dbConn = null;
2114
        int serialNumber = -1;
2115

    
2116
        try {
2117
            valtext = ((String[]) params.get("valtext"))[0];
2118
        } catch (Exception nullpe) {
2119

    
2120
            String docid = null;
2121
            try {
2122
                // Find the document id number
2123
                docid = ((String[]) params.get("docid"))[0];
2124

    
2125
                // Get the document indicated from the db
2126
                DocumentImpl xmldoc = new DocumentImpl(docid);
2127
                valtext = xmldoc.toString();
2128

    
2129
            } catch (NullPointerException npe) {
2130

    
2131
                out.println("<error>Error getting document ID: " + docid
2132
                        + "</error>");
2133
                //if ( conn != null ) { util.returnConnection(conn); }
2134
                return;
2135
            } catch (Exception e) {
2136

    
2137
                out.println(e.getMessage());
2138
            }
2139
        }
2140

    
2141
        try {
2142
            // get a connection from the pool
2143
            dbConn = DBConnectionPool
2144
                    .getDBConnection("MetaCatServlet.handleValidateAction");
2145
            serialNumber = dbConn.getCheckOutSerialNumber();
2146
            DBValidate valobj = new DBValidate(saxparser, dbConn);
2147
            boolean valid = valobj.validateString(valtext);
2148

    
2149
            // set content type and other response header fields first
2150

    
2151
            out.println(valobj.returnErrors());
2152

    
2153
        } catch (NullPointerException npe2) {
2154
            // set content type and other response header fields first
2155

    
2156
            out.println("<error>Error validating document.</error>");
2157
        } catch (Exception e) {
2158

    
2159
            out.println(e.getMessage());
2160
        } finally {
2161
            // Return db connection
2162
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2163
        }
2164
    }
2165

    
2166
    /**
2167
     * Handle "getrevsionanddoctype" action Given a docid, return it's current
2168
     * revision and doctype from data base The output is String look like
2169
     * "rev;doctype"
2170
     */
2171
    private void handleGetRevisionAndDocTypeAction(PrintWriter out,
2172
            Hashtable params)
2173
    {
2174
        // To store doc parameter
2175
        String[] docs = new String[10];
2176
        // Store a single doc id
2177
        String givenDocId = null;
2178
        // Get docid from parameters
2179
        if (params.containsKey("docid")) {
2180
            docs = (String[]) params.get("docid");
2181
        }
2182
        // Get first docid form string array
2183
        givenDocId = docs[0];
2184

    
2185
        try {
2186
            // Make sure there is a docid
2187
            if (givenDocId == null || givenDocId.equals("")) { throw new Exception(
2188
                    "User didn't specify docid!"); }//if
2189

    
2190
            // Create a DBUtil object
2191
            DBUtil dbutil = new DBUtil();
2192
            // Get a rev and doctype
2193
            String revAndDocType = dbutil
2194
                    .getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
2195
            out.println(revAndDocType);
2196

    
2197
        } catch (Exception e) {
2198
            // Handle exception
2199
            out.println("<?xml version=\"1.0\"?>");
2200
            out.println("<error>");
2201
            out.println(e.getMessage());
2202
            out.println("</error>");
2203
        }
2204

    
2205
    }
2206

    
2207
    /**
2208
     * Handle "getaccesscontrol" action. Read Access Control List from db
2209
     * connection in XML format
2210
     */
2211
    private void handleGetAccessControlAction(PrintWriter out,
2212
            Hashtable params, HttpServletResponse response, String username,
2213
            String[] groupnames)
2214
    {
2215
        DBConnection dbConn = null;
2216
        int serialNumber = -1;
2217
        String docid = ((String[]) params.get("docid"))[0];
2218

    
2219
        try {
2220

    
2221
            // get connection from the pool
2222
            dbConn = DBConnectionPool
2223
                    .getDBConnection("MetaCatServlet.handleGetAccessControlAction");
2224
            serialNumber = dbConn.getCheckOutSerialNumber();
2225
            AccessControlList aclobj = new AccessControlList(dbConn);
2226
            String acltext = aclobj.getACL(docid, username, groupnames);
2227
            out.println(acltext);
2228

    
2229
        } catch (Exception e) {
2230
            out.println("<?xml version=\"1.0\"?>");
2231
            out.println("<error>");
2232
            out.println(e.getMessage());
2233
            out.println("</error>");
2234
        } finally {
2235
            // Retrun db connection to pool
2236
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2237
        }
2238
    }
2239

    
2240
    /**
2241
     * Handle the "getprincipals" action. Read all principals from
2242
     * authentication scheme in XML format
2243
     */
2244
    private void handleGetPrincipalsAction(PrintWriter out, String user,
2245
            String password)
2246
    {
2247
        try {
2248
            AuthSession auth = new AuthSession();
2249
            String principals = auth.getPrincipals(user, password);
2250
            out.println(principals);
2251

    
2252
        } catch (Exception e) {
2253
            out.println("<?xml version=\"1.0\"?>");
2254
            out.println("<error>");
2255
            out.println(e.getMessage());
2256
            out.println("</error>");
2257
        }
2258
    }
2259

    
2260
    /**
2261
     * Handle "getdoctypes" action. Read all doctypes from db connection in XML
2262
     * format
2263
     */
2264
    private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
2265
            HttpServletResponse response)
2266
    {
2267
        try {
2268
            DBUtil dbutil = new DBUtil();
2269
            String doctypes = dbutil.readDoctypes();
2270
            out.println(doctypes);
2271
        } catch (Exception e) {
2272
            out.println("<?xml version=\"1.0\"?>");
2273
            out.println("<error>");
2274
            out.println(e.getMessage());
2275
            out.println("</error>");
2276
        }
2277
    }
2278

    
2279
    /**
2280
     * Handle the "getdtdschema" action. Read DTD or Schema file for a given
2281
     * doctype from Metacat catalog system
2282
     */
2283
    private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
2284
            HttpServletResponse response)
2285
    {
2286

    
2287
        String doctype = null;
2288
        String[] doctypeArr = (String[]) params.get("doctype");
2289

    
2290
        // get only the first doctype specified in the list of doctypes
2291
        // it could be done for all doctypes in that list
2292
        if (doctypeArr != null) {
2293
            doctype = ((String[]) params.get("doctype"))[0];
2294
        }
2295

    
2296
        try {
2297
            DBUtil dbutil = new DBUtil();
2298
            String dtdschema = dbutil.readDTDSchema(doctype);
2299
            out.println(dtdschema);
2300

    
2301
        } catch (Exception e) {
2302
            out.println("<?xml version=\"1.0\"?>");
2303
            out.println("<error>");
2304
            out.println(e.getMessage());
2305
            out.println("</error>");
2306
        }
2307

    
2308
    }
2309

    
2310
    /**
2311
     * Handle the "getlastdocid" action. Get the latest docid with rev number
2312
     * from db connection in XML format
2313
     */
2314
    private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
2315
            HttpServletResponse response)
2316
    {
2317

    
2318
        String scope = ((String[]) params.get("scope"))[0];
2319
        if (scope == null) {
2320
            scope = ((String[]) params.get("username"))[0];
2321
        }
2322

    
2323
        try {
2324

    
2325
            DBUtil dbutil = new DBUtil();
2326
            String lastDocid = dbutil.getMaxDocid(scope);
2327
            out.println("<?xml version=\"1.0\"?>");
2328
            out.println("<lastDocid>");
2329
            out.println("  <scope>" + scope + "</scope>");
2330
            out.println("  <docid>" + lastDocid + "</docid>");
2331
            out.println("</lastDocid>");
2332

    
2333
        } catch (Exception e) {
2334
            out.println("<?xml version=\"1.0\"?>");
2335
            out.println("<error>");
2336
            out.println(e.getMessage());
2337
            out.println("</error>");
2338
        }
2339
    }
2340

    
2341
    /**
2342
     * Print a report from the event log based on filter parameters passed in
2343
     * from the web.
2344
     *
2345
     * @param params the parameters from the web request
2346
     * @param request the http request object for getting request details
2347
     * @param response the http response object for writing output
2348
     */
2349
    private void handleGetLogAction(Hashtable params, HttpServletRequest request,
2350
            HttpServletResponse response, String username, String[] groups)
2351
    {
2352
        try {
2353
            response.setContentType("text/xml");
2354
            PrintWriter out = response.getWriter();
2355

    
2356
            // Check that the user is authenticated as an administrator account
2357
            if (!MetaCatUtil.isAdministrator(username, groups)) {
2358
                out.print("<error>");
2359
                out.print("The user \"" + username +
2360
                        "\" is not authorized for this action.");
2361
                out.print("</error>");
2362
                return;
2363
            }
2364

    
2365
            // Get all of the parameters in the correct formats
2366
            String[] ipAddress = (String[])params.get("ipaddress");
2367
            String[] principal = (String[])params.get("principal");
2368
            String[] docid = (String[])params.get("docid");
2369
            String[] event = (String[])params.get("event");
2370
            String[] startArray = (String[]) params.get("start");
2371
            String[] endArray = (String[]) params.get("end");
2372
            String start = null;
2373
            String end = null;
2374
            if (startArray != null) {
2375
                start = startArray[0];
2376
            }
2377
            if (endArray != null) {
2378
                end = endArray[0];
2379
            }
2380
            Timestamp startDate = null;
2381
            Timestamp endDate = null;
2382
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
2383
            try {
2384
                if (start != null) {
2385
                    startDate = new Timestamp((format.parse(start)).getTime());
2386
                }
2387
                if (end != null) {
2388
                    endDate = new Timestamp((format.parse(end)).getTime());
2389
                }
2390
            } catch (ParseException e) {
2391
                System.out.println("Failed to created Timestamp from input.");
2392
            }
2393

    
2394
            // Request the report by passing the filter parameters
2395
            out.println(EventLog.getInstance().getReport(ipAddress, principal,
2396
                    docid, event, startDate, endDate));
2397
            out.close();
2398
        } catch (IOException e) {
2399
            logMetacat.error(
2400
                    "Could not open http response for writing: " + e.getMessage());
2401
        }
2402
    }
2403

    
2404
    /**
2405
     * Rebuild the index for one or more documents. If the docid parameter is
2406
     * provided, rebuild for just that one document or list of documents. If
2407
     * not, then rebuild the index for all documents in the xml_documents
2408
     * table.
2409
     *
2410
     * @param params the parameters from the web request
2411
     * @param request the http request object for getting request details
2412
     * @param response the http response object for writing output
2413
     * @param username the username of the authenticated user
2414
     */
2415
    private void handleBuildIndexAction(Hashtable params,
2416
            HttpServletRequest request, HttpServletResponse response,
2417
            String username, String[] groups)
2418
    {
2419
        // Get all of the parameters in the correct formats
2420
        String[] docid = (String[])params.get("docid");
2421

    
2422
        // Rebuild the indices for appropriate documents
2423
        try {
2424
            response.setContentType("text/xml");
2425
            PrintWriter out = response.getWriter();
2426

    
2427
            // Check that the user is authenticated as an administrator account
2428
            if (!MetaCatUtil.isAdministrator(username, groups)) {
2429
                out.print("<error>");
2430
                out.print("The user \"" + username +
2431
                        "\" is not authorized for this action.");
2432
                out.print("</error>");
2433
                return;
2434
            }
2435

    
2436
            // Process the documents
2437
            out.println("<success>");
2438
            if (docid == null || docid.length == 0) {
2439
                // Process all of the documents
2440
                try {
2441
                    Vector documents = getDocumentList();
2442
                    Iterator it = documents.iterator();
2443
                    while (it.hasNext()) {
2444
                        String id = (String) it.next();
2445
                        buildDocumentIndex(id, out);
2446
                    }
2447
                } catch (SQLException se) {
2448
                    out.print("<error>");
2449
                    out.print(se.getMessage());
2450
                    out.println("</error>");
2451
                }
2452
            } else {
2453
                // Only process the requested documents
2454
                for (int i = 0; i < docid.length; i++) {
2455
                    buildDocumentIndex(docid[i], out);
2456
                }
2457
            }
2458
            out.println("</success>");
2459
            out.close();
2460
        } catch (IOException e) {
2461
            logMetacat.error(
2462
                    "Could not open http response for writing: "
2463
                    + e.getMessage());
2464
        }
2465
    }
2466

    
2467
    /**
2468
     * Build the index for one document by reading the document and
2469
     * calling its buildIndex() method.
2470
     *
2471
     * @param docid the document (with revision) to rebuild
2472
     * @param out the PrintWriter to which output is printed
2473
     */
2474
    private void buildDocumentIndex(String docid, PrintWriter out)
2475
    {
2476
        try {
2477
            DocumentImpl doc = new DocumentImpl(docid, false);
2478
            doc.buildIndex();
2479
            out.print("<docid>" + docid);
2480
            out.println("</docid>");
2481
        } catch (McdbException me) {
2482
            out.print("<error>");
2483
            out.print(me.getMessage());
2484
            out.println("</error>");
2485
        }
2486
    }
2487

    
2488
    /**
2489
     * Handle documents passed to metacat that are encoded using the
2490
     * "multipart/form-data" mime type. This is typically used for uploading
2491
     * data files which may be binary and large.
2492
     */
2493
    private void handleMultipartForm(HttpServletRequest request,
2494
            HttpServletResponse response)
2495
    {
2496
        PrintWriter out = null;
2497
        String action = null;
2498

    
2499
        // Parse the multipart form, and save the parameters in a Hashtable and
2500
        // save the FileParts in a hashtable
2501

    
2502
        Hashtable params = new Hashtable();
2503
        Hashtable fileList = new Hashtable();
2504
        int sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit")))
2505
                .intValue();
2506
        logMetacat.info(
2507
                "The limit size of data file is: " + sizeLimit);
2508

    
2509
        try {
2510
            // MBJ: need to put filesize limit in Metacat config
2511
            // (metacat.properties)
2512
            MultipartParser mp = new MultipartParser(request,
2513
                    sizeLimit * 1024 * 1024);
2514
            Part part;
2515
            while ((part = mp.readNextPart()) != null) {
2516
                String name = part.getName();
2517

    
2518
                if (part.isParam()) {
2519
                    // it's a parameter part
2520
                    ParamPart paramPart = (ParamPart) part;
2521
                    String value = paramPart.getStringValue();
2522
                    params.put(name, value);
2523
                    if (name.equals("action")) {
2524
                        action = value;
2525
                    }
2526
                } else if (part.isFile()) {
2527
                    // it's a file part
2528
                    FilePart filePart = (FilePart) part;
2529
                    fileList.put(name, filePart);
2530

    
2531
                    // Stop once the first file part is found, otherwise going
2532
                    // onto the
2533
                    // next part prevents access to the file contents. So...for
2534
                    // upload
2535
                    // to work, the datafile must be the last part
2536
                    break;
2537
                }
2538
            }
2539
        } catch (IOException ioe) {
2540
            try {
2541
                out = response.getWriter();
2542
            } catch (IOException ioe2) {
2543
                logMetacat.fatal("Fatal Error: couldn't get response output stream.");
2544
            }
2545
            out.println("<?xml version=\"1.0\"?>");
2546
            out.println("<error>");
2547
            out.println("Error: problem reading multipart data.");
2548
            out.println("</error>");
2549
        }
2550

    
2551
        // Get the session information
2552
        String username = null;
2553
        String password = null;
2554
        String[] groupnames = null;
2555
        String sess_id = null;
2556

    
2557
        // be aware of session expiration on every request
2558
        HttpSession sess = request.getSession(true);
2559
        if (sess.isNew()) {
2560
            // session expired or has not been stored b/w user requests
2561
            username = "public";
2562
            sess.setAttribute("username", username);
2563
        } else {
2564
            username = (String) sess.getAttribute("username");
2565
            password = (String) sess.getAttribute("password");
2566
            groupnames = (String[]) sess.getAttribute("groupnames");
2567
            try {
2568
                sess_id = (String) sess.getId();
2569
            } catch (IllegalStateException ise) {
2570
                System.out
2571
                        .println("error in  handleMultipartForm: this shouldn't "
2572
                                + "happen: the session should be valid: "
2573
                                + ise.getMessage());
2574
            }
2575
        }
2576

    
2577
        // Get the out stream
2578
        try {
2579
            out = response.getWriter();
2580
        } catch (IOException ioe2) {
2581
            logMetacat.error("Fatal Error: couldn't get response "
2582
                    + "output stream.");
2583
        }
2584

    
2585
        if (action.equals("upload")) {
2586
            if (username != null && !username.equals("public")) {
2587
                handleUploadAction(request, out, params, fileList, username,
2588
                        groupnames);
2589
            } else {
2590

    
2591
                out.println("<?xml version=\"1.0\"?>");
2592
                out.println("<error>");
2593
                out.println("Permission denied for " + action);
2594
                out.println("</error>");
2595
            }
2596
        } else {
2597
            /*
2598
             * try { out = response.getWriter(); } catch (IOException ioe2) {
2599
             * System.err.println("Fatal Error: couldn't get response output
2600
             * stream.");
2601
             */
2602
            out.println("<?xml version=\"1.0\"?>");
2603
            out.println("<error>");
2604
            out.println(
2605
                    "Error: action not registered.  Please report this error.");
2606
            out.println("</error>");
2607
        }
2608
        out.close();
2609
    }
2610

    
2611
    /**
2612
     * Handle the upload action by saving the attached file to disk and
2613
     * registering it in the Metacat db
2614
     */
2615
    private void handleUploadAction(HttpServletRequest request,
2616
            PrintWriter out, Hashtable params, Hashtable fileList,
2617
            String username, String[] groupnames)
2618
    {
2619
        //PrintWriter out = null;
2620
        //Connection conn = null;
2621
        String action = null;
2622
        String docid = null;
2623

    
2624
        /*
2625
         * response.setContentType("text/xml"); try { out =
2626
         * response.getWriter(); } catch (IOException ioe2) {
2627
         * System.err.println("Fatal Error: couldn't get response output
2628
         * stream.");
2629
         */
2630

    
2631
        if (params.containsKey("docid")) {
2632
            docid = (String) params.get("docid");
2633
        }
2634

    
2635
        // Make sure we have a docid and datafile
2636
        if (docid != null && fileList.containsKey("datafile")) {
2637

    
2638
            // Get a reference to the file part of the form
2639
            FilePart filePart = (FilePart) fileList.get("datafile");
2640
            String fileName = filePart.getFileName();
2641
            logMetacat.warn("Uploading filename: " + fileName);
2642

    
2643
            // Check if the right file existed in the uploaded data
2644
            if (fileName != null) {
2645

    
2646
                try {
2647
                    //logMetacat.info("Upload datafile " + docid
2648
                    // +"...", 10);
2649
                    //If document get lock data file grant
2650
                    if (DocumentImpl.getDataFileLockGrant(docid)) {
2651
                        // register the file in the database (which generates
2652
                        // an exception
2653
                        //if the docid is not acceptable or other untoward
2654
                        // things happen
2655
                        DocumentImpl.registerDocument(fileName, "BIN", docid,
2656
                                username, groupnames);
2657

    
2658
                        // Save the data file to disk using "docid" as the name
2659
                        dataDirectory.mkdirs();
2660
                        File newFile = new File(dataDirectory, docid);
2661
                        long size = filePart.writeTo(newFile);
2662

    
2663
                        EventLog.getInstance().log(request.getRemoteAddr(),
2664
                                username, docid, "upload");
2665
                        // Force replication this data file
2666
                        // To data file, "insert" and update is same
2667
                        // The fourth parameter is null. Because it is
2668
                        // notification server
2669
                        // and this method is in MetaCatServerlet. It is
2670
                        // original command,
2671
                        // not get force replication info from another metacat
2672
                        ForceReplicationHandler frh = new ForceReplicationHandler(
2673
                                docid, "insert", false, null);
2674

    
2675
                        // set content type and other response header fields
2676
                        // first
2677
                        out.println("<?xml version=\"1.0\"?>");
2678
                        out.println("<success>");
2679
                        out.println("<docid>" + docid + "</docid>");
2680
                        out.println("<size>" + size + "</size>");
2681
                        out.println("</success>");
2682
                    }
2683

    
2684
                } catch (Exception e) {
2685
                    out.println("<?xml version=\"1.0\"?>");
2686
                    out.println("<error>");
2687
                    out.println(e.getMessage());
2688
                    out.println("</error>");
2689
                }
2690
            } else {
2691
                // the field did not contain a file
2692
                out.println("<?xml version=\"1.0\"?>");
2693
                out.println("<error>");
2694
                out.println("The uploaded data did not contain a valid file.");
2695
                out.println("</error>");
2696
            }
2697
        } else {
2698
            // Error bcse docid missing or file missing
2699
            out.println("<?xml version=\"1.0\"?>");
2700
            out.println("<error>");
2701
            out.println("The uploaded data did not contain a valid docid "
2702
                    + "or valid file.");
2703
            out.println("</error>");
2704
        }
2705
    }
2706

    
2707
    /*
2708
     * A method to handle set access action
2709
     */
2710
    private void handleSetAccessAction(PrintWriter out, Hashtable params,
2711
            String username)
2712
    {
2713
        String[] docList = null;
2714
        String[] principalList = null;
2715
        String[] permissionList = null;
2716
        String[] permTypeList = null;
2717
        String[] permOrderList = null;
2718
        String permission = null;
2719
        String permType = null;
2720
        String permOrder = null;
2721
        Vector errorList = new Vector();
2722
        String error = null;
2723
        Vector successList = new Vector();
2724
        String success = null;
2725

    
2726
        // Get parameters
2727
        if (params.containsKey("docid")) {
2728
            docList = (String[]) params.get("docid");
2729
        }
2730
        if (params.containsKey("principal")) {
2731
            principalList = (String[]) params.get("principal");
2732
        }
2733
        if (params.containsKey("permission")) {
2734
            permissionList = (String[]) params.get("permission");
2735

    
2736
        }
2737
        if (params.containsKey("permType")) {
2738
            permTypeList = (String[]) params.get("permType");
2739

    
2740
        }
2741
        if (params.containsKey("permOrder")) {
2742
            permOrderList = (String[]) params.get("permOrder");
2743

    
2744
        }
2745

    
2746
        // Make sure the parameter is not null
2747
        if (docList == null || principalList == null || permTypeList == null
2748
                || permissionList == null) {
2749
            error = "Please check your parameter list, it should look like: "
2750
                    + "?action=setaccess&docid=pipeline.1.1&principal=public"
2751
                    + "&permission=read&permType=allow&permOrder=allowFirst";
2752
            errorList.addElement(error);
2753
            outputResponse(successList, errorList, out);
2754
            return;
2755
        }
2756

    
2757
        // Only select first element for permission, type and order
2758
        permission = permissionList[0];
2759
        permType = permTypeList[0];
2760
        if (permOrderList != null) {
2761
            permOrder = permOrderList[0];
2762
        }
2763

    
2764
        // Get package doctype set
2765
        Vector packageSet = MetaCatUtil.getOptionList(MetaCatUtil
2766
                .getOption("packagedoctypeset"));
2767
        //debug
2768
        if (packageSet != null) {
2769
            for (int i = 0; i < packageSet.size(); i++) {
2770
                logMetacat.info("doctype in package set: "
2771
                        + (String) packageSet.elementAt(i));
2772
            }
2773
        }
2774

    
2775
        // handle every accessionNumber
2776
        for (int i = 0; i < docList.length; i++) {
2777
            String accessionNumber = docList[i];
2778
            String owner = null;
2779
            String publicId = null;
2780
            // Get document owner and public id
2781
            try {
2782
                owner = getFieldValueForDoc(accessionNumber, "user_owner");
2783
                publicId = getFieldValueForDoc(accessionNumber, "doctype");
2784
            } catch (Exception e) {
2785
                logMetacat.error("Error in handleSetAccessAction: "
2786
                        + e.getMessage());
2787
                error = "Error in set access control for document - "
2788
                        + accessionNumber + e.getMessage();
2789
                errorList.addElement(error);
2790
                continue;
2791
            }
2792
            //check if user is the owner. Only owner can do owner
2793
            if (username == null || owner == null || !username.equals(owner)) {
2794
                error = "User - " + username
2795
                        + " does not have permission to set "
2796
                        + "access control for docid - " + accessionNumber;
2797
                errorList.addElement(error);
2798
                continue;
2799
            }
2800

    
2801
            // If docid publicid is BIN data file or other beta4, 6 package
2802
            // document
2803
            // we could not do set access control. Because we don't want
2804
            // inconsistent
2805
            // to its access docuemnt
2806
            if (publicId != null && packageSet != null
2807
                    && packageSet.contains(publicId)) {
2808
                error = "Could not set access control to document "
2809
                        + accessionNumber
2810
                        + "because it is in a pakcage and it has a access file for it";
2811
                errorList.addElement(error);
2812
                continue;
2813
            }
2814

    
2815
            // for every principle
2816
            for (int j = 0; j < principalList.length; j++) {
2817
                String principal = principalList[j];
2818
                try {
2819
                    //insert permission
2820
                    AccessControlForSingleFile accessControl = new AccessControlForSingleFile(
2821
                            accessionNumber, principal, permission, permType,
2822
                            permOrder);
2823
                    accessControl.insertPermissions();
2824
                    success = "Set access control to document "
2825
                            + accessionNumber + " successfully";
2826
                    successList.addElement(success);
2827
                } catch (Exception ee) {
2828
                    logMetacat.error(
2829
                            "Erorr in handleSetAccessAction2: "
2830
                                    + ee.getMessage());
2831
                    error = "Faild to set access control for document "
2832
                            + accessionNumber + " because " + ee.getMessage();
2833
                    errorList.addElement(error);
2834
                    continue;
2835
                }
2836
            }
2837
        }
2838
        outputResponse(successList, errorList, out);
2839
    }
2840

    
2841
    /*
2842
     * A method try to determin a docid's public id, if couldn't find null will
2843
     * be returned.
2844
     */
2845
    private String getFieldValueForDoc(String accessionNumber, String fieldName)
2846
            throws Exception
2847
    {
2848
        if (accessionNumber == null || accessionNumber.equals("")
2849
                || fieldName == null || fieldName.equals("")) { throw new Exception(
2850
                "Docid or field name was not specified"); }
2851

    
2852
        PreparedStatement pstmt = null;
2853
        ResultSet rs = null;
2854
        String fieldValue = null;
2855
        String docId = null;
2856
        DBConnection conn = null;
2857
        int serialNumber = -1;
2858

    
2859
        // get rid of revision if access number has
2860
        docId = MetaCatUtil.getDocIdFromString(accessionNumber);
2861
        try {
2862
            //check out DBConnection
2863
            conn = DBConnectionPool
2864
                    .getDBConnection("MetaCatServlet.getPublicIdForDoc");
2865
            serialNumber = conn.getCheckOutSerialNumber();
2866
            pstmt = conn.prepareStatement("SELECT " + fieldName
2867
                    + " FROM xml_documents " + "WHERE docid = ? ");
2868

    
2869
            pstmt.setString(1, docId);
2870
            pstmt.execute();
2871
            rs = pstmt.getResultSet();
2872
            boolean hasRow = rs.next();
2873
            int perm = 0;
2874
            if (hasRow) {
2875
                fieldValue = rs.getString(1);
2876
            } else {
2877
                throw new Exception("Could not find document: "
2878
                        + accessionNumber);
2879
            }
2880
        } catch (Exception e) {
2881
            logMetacat.error(
2882
                    "Exception in MetacatServlet.getPublicIdForDoc: "
2883
                            + e.getMessage());
2884
            throw e;
2885
        } finally {
2886
            try {
2887
                rs.close();
2888
                pstmt.close();
2889

    
2890
            } finally {
2891
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2892
            }
2893
        }
2894
        return fieldValue;
2895
    }
2896

    
2897
    /*
2898
     * Get the list of documents from the database and return the list in an
2899
     * Vector of identifiers.
2900
     *
2901
     * @ returns the array of identifiers
2902
     */
2903
    private Vector getDocumentList() throws SQLException
2904
    {
2905
        Vector docList = new Vector();
2906
        PreparedStatement pstmt = null;
2907
        ResultSet rs = null;
2908
        DBConnection conn = null;
2909
        int serialNumber = -1;
2910

    
2911
        try {
2912
            //check out DBConnection
2913
            conn = DBConnectionPool
2914
                    .getDBConnection("MetaCatServlet.getDocumentList");
2915
            serialNumber = conn.getCheckOutSerialNumber();
2916
            pstmt = conn.prepareStatement("SELECT docid, rev"
2917
                    + " FROM xml_documents ");
2918
            pstmt.execute();
2919
            rs = pstmt.getResultSet();
2920
            while (rs.next()) {
2921
                String docid = rs.getString(1);
2922
                String rev = rs.getString(2);
2923
                docList.add(docid + "." + rev);
2924
            }
2925
        } catch (SQLException e) {
2926
            logMetacat.error(
2927
                    "Exception in MetacatServlet.getDocumentList: "
2928
                            + e.getMessage());
2929
            throw e;
2930
        } finally {
2931
            try {
2932
                rs.close();
2933
                pstmt.close();
2934

    
2935
            } catch (SQLException se) {
2936
                logMetacat.error(
2937
                    "Exception in MetacatServlet.getDocumentList: "
2938
                            + se.getMessage());
2939
                throw se;
2940
            } finally {
2941
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2942
            }
2943
        }
2944
        return docList;
2945
    }
2946

    
2947
    /*
2948
     * A method to output setAccess action result
2949
     */
2950
    private void outputResponse(Vector successList, Vector errorList,
2951
            PrintWriter out)
2952
    {
2953
        boolean error = false;
2954
        boolean success = false;
2955
        // Output prolog
2956
        out.println(PROLOG);
2957
        // output success message
2958
        if (successList != null) {
2959
            for (int i = 0; i < successList.size(); i++) {
2960
                out.println(SUCCESS);
2961
                out.println((String) successList.elementAt(i));
2962
                out.println(SUCCESSCLOSE);
2963
                success = true;
2964
            }
2965
        }
2966
        // output error message
2967
        if (errorList != null) {
2968
            for (int i = 0; i < errorList.size(); i++) {
2969
                out.println(ERROR);
2970
                out.println((String) errorList.elementAt(i));
2971
                out.println(ERRORCLOSE);
2972
                error = true;
2973
            }
2974
        }
2975

    
2976
        // if no error and no success info, send a error that nothing happened
2977
        if (!error && !success) {
2978
            out.println(ERROR);
2979
            out.println("Nothing happend for setaccess action");
2980
            out.println(ERRORCLOSE);
2981
        }
2982
    }
2983
    
2984
    /**
2985
     * Method to get session table which store the session info
2986
     * @return
2987
     */
2988
    public static Hashtable getSessionHash()
2989
    {
2990
        return sessionHash;
2991
    }
2992
    
2993
    /*
2994
     * If the given docid only have one seperter, we need 
2995
     * append rev for it. The rev come from xml_documents
2996
     */
2997
    private static String appendRev(String docid) throws Exception
2998
    {
2999
        String newAccNum = null;
3000
        String separator = MetaCatUtil.getOption("accNumSeparator");
3001
        int firstIndex = docid.indexOf(separator);
3002
        int lastIndex = docid.lastIndexOf(separator);
3003
        if (firstIndex == lastIndex)
3004
        {
3005
            
3006
           //only one seperater
3007
            int rev = DBUtil.getLatestRevisionInDocumentTable(docid);
3008
            if (rev == -1)
3009
            {
3010
                throw new Exception("Couldn't find the document "+docid);
3011
            }
3012
            else
3013
            {
3014
                newAccNum = docid+ separator+ rev;
3015
            }
3016
        }
3017
        else
3018
        {
3019
            // in other suituation we don't change the docid
3020
            newAccNum = docid;
3021
        }
3022
        logMetacat.warn("The docid will be read is "+newAccNum);
3023
        return newAccNum;
3024
    }
3025
}
(44-44/65)