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, Matthew Perry
7
 *    Release: @release@
8
 *
9
 *   '$Author: perry $'
10
 *     '$Date: 2006-09-18 11:21:58 -0700 (Mon, 18 Sep 2006) $'
11
 * '$Revision: 3047 $'
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.HashMap;
46
import java.util.Hashtable;
47
import java.util.Iterator;
48
import java.util.Properties;
49
import java.util.Timer;
50
import java.util.Vector;
51
import java.util.zip.ZipEntry;
52
import java.util.zip.ZipOutputStream;
53

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

    
63
import org.apache.log4j.Logger;
64
import org.apache.log4j.PropertyConfigurator;
65
import org.ecoinformatics.eml.EMLParser;
66

    
67
import com.oreilly.servlet.multipart.FilePart;
68
import com.oreilly.servlet.multipart.MultipartParser;
69
import com.oreilly.servlet.multipart.ParamPart;
70
import com.oreilly.servlet.multipart.Part;
71

    
72
import edu.ucsb.nceas.utilities.Options;
73
import edu.ucsb.nceas.metacat.spatial.SpatialHarvester;
74
import edu.ucsb.nceas.metacat.spatial.SpatialQuery;
75

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

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

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

    
166
            MetaCatUtil util = new MetaCatUtil();
167
            
168
            //initialize DBConnection pool
169
            DBConnectionPool connPool = DBConnectionPool.getInstance();
170
            
171
            // Index the paths specified in the metacat.properties
172
            checkIndexPaths();
173

    
174
            // initiate the indexing Queue
175
            IndexingQueue.getInstance();
176
            
177
            // start the IndexingThread if indexingTimerTaskTime more than 0. 
178
            // It will index all the documents not yet indexed in the database             
179
            int indexingTimerTaskTime = Integer.parseInt(MetaCatUtil.getOption("indexingTimerTaskTime"));
180
            if(indexingTimerTaskTime > 0){
181
            	timer = new Timer();
182
            	timer.schedule(new IndexingTimerTask(), 0, indexingTimerTaskTime);
183
            }
184
            
185
            // read the config files: 
186
            Vector skins = MetaCatUtil.getOptionList(MetaCatUtil.getOption("skinconfigfiles"));
187
            String skinName, skinDirPath = null;
188
            File skinPropertyFile = null;
189
           
190
            for (int i = 0; i < skins.size(); i++) {
191
            	skinName = (String) skins.elementAt(i);
192
                skinDirPath = context.getRealPath(CONFIG_DIR + "/skin.configs/" + skinName);
193
                skinPropertyFile = new File(skinDirPath, skinName + ".properties"); 
194
                Properties skinOption = null;
195
                try	{
196
                	skinOption = new Properties();
197
                    FileInputStream fis = new FileInputStream(skinPropertyFile);
198
                    skinOption.load(fis);
199
                    fis.close();
200
                } catch (IOException ioe) {
201
                    Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
202
                    logMetacat.error("Error in loading options for skin " + "skinName" +" : "
203
                            + ioe.getMessage());
204
                }                
205
                MetaCatUtil.skinconfigs.put(skinName, skinOption);
206
            }
207

    
208
            /*
209
             *  If spatial option is turned on and set to regenerate the
210
             *  spatial cache on restart, trigger the harvester 
211
             */
212
            if ( MetaCatUtil.getOption("runSpatialOption").equals("true") &&
213
                 MetaCatUtil.getOption("regenerateCacheOnRestart").equals("true") ) {
214

    
215
                // Begin timer
216
                long before = System.currentTimeMillis();
217
                 
218
                // regenerate the entire spatial cache
219
                // may be expensive with many documents
220
                SpatialHarvester sh = new SpatialHarvester();
221
                sh.regenerate();
222
                sh.destroy();
223

    
224
                // End timer
225
                long after = System.currentTimeMillis();
226
                MetaCatUtil.printMessage(" ------ Spatial Harvester Time  " + (after - before) + "ms");
227

    
228
	    } else {
229
                MetaCatUtil.printMessage(" \n **** Spatial cache is not set to regenerate on restart");
230
            }
231
           
232
           
233
            MetaCatUtil.printMessage("Metacat (" + Version.getVersion()
234
                               + ") initialized.");
235

    
236
        } catch (ServletException ex) {
237
            throw ex;
238
        } catch (SQLException e) {
239
            Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
240
            logMetacat.error("Error in MetacatServlet.init: "
241
                    + e.getMessage());
242
        }
243
    }
244

    
245
    /**
246
     * Close all db connections from the pool
247
     */
248
    public void destroy()
249
    {
250
        // Close all db connection
251
        System.out.println("Destroying MetacatServlet");
252
        timer.cancel();
253
        IndexingQueue.getInstance().setMetacatRunning(false);
254
        DBConnectionPool.release();
255
    }
256

    
257
    /** Handle "GET" method requests from HTTP clients */
258
    public void doGet(HttpServletRequest request, HttpServletResponse response)
259
            throws ServletException, IOException
260
    {
261

    
262
        // Process the data and send back the response
263
        handleGetOrPost(request, response);
264
    }
265

    
266
    /** Handle "POST" method requests from HTTP clients */
267
    public void doPost(HttpServletRequest request, HttpServletResponse response)
268
            throws ServletException, IOException
269
    {
270

    
271
        // Process the data and send back the response
272
        handleGetOrPost(request, response);
273
    }
274

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

    
413
    /**
414
     * Control servlet response depending on the action parameter specified
415
     */
416
    private void handleGetOrPost(HttpServletRequest request,
417
            HttpServletResponse response) throws ServletException, IOException
418
    {
419
        MetaCatUtil util = new MetaCatUtil();
420
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
421
        
422
        /*
423
         * logMetacat.debug("Connection pool size: "
424
         * +connPool.getSizeOfDBConnectionPool(),10);
425
         * logMetacat.debug("Free DBConnection number: "
426
         */
427
        //If all DBConnection in the pool are free and DBConnection pool
428
        //size is greater than initial value, shrink the connection pool
429
        //size to initial value
430
        DBConnectionPool.shrinkDBConnectionPoolSize();
431

    
432
        //Debug message to print out the method which have a busy DBConnection
433
        try {
434
            DBConnectionPool pool = DBConnectionPool.getInstance();
435
            pool.printMethodNameHavingBusyDBConnection();
436
        } catch (SQLException e) {
437
            logMetacat.error("Error in MetacatServlet.handleGetOrPost: "
438
                    + e.getMessage());
439
            e.printStackTrace();
440
        }
441

    
442
        String ctype = request.getContentType();
443
        if (ctype != null && ctype.startsWith("multipart/form-data")) {
444
            handleMultipartForm(request, response);
445
        } else {
446

    
447
            String name = null;
448
            String[] value = null;
449
            String[] docid = new String[3];
450
            Hashtable params = new Hashtable();
451
            Enumeration paramlist = request.getParameterNames();
452

    
453
            while (paramlist.hasMoreElements()) {
454

    
455
                name = (String) paramlist.nextElement();
456
                value = request.getParameterValues(name);
457

    
458
                // Decode the docid and mouse click information
459
                if (name.endsWith(".y")) {
460
                    docid[0] = name.substring(0, name.length() - 2);
461
                    params.put("docid", docid);
462
                    name = "ypos";
463
                }
464
                if (name.endsWith(".x")) {
465
                    name = "xpos";
466
                }
467

    
468
                params.put(name, value);
469
            }
470

    
471
            //handle param is emptpy
472
            if (params.isEmpty() || params == null) { return; }
473

    
474
            //if the user clicked on the input images, decode which image
475
            //was clicked then set the action.
476
            if(params.get("action") == null){
477
                PrintWriter out = response.getWriter();
478
                response.setContentType("text/xml");
479
                out.println("<?xml version=\"1.0\"?>");
480
                out.println("<error>");
481
                out.println("Action not specified");
482
                out.println("</error>");
483
                out.close();
484
                return;
485
            }
486

    
487
            String action = ((String[]) params.get("action"))[0];
488
            logMetacat.info("Action is: " + action);
489

    
490
            // This block handles session management for the servlet
491
            // by looking up the current session information for all actions
492
            // other than "login" and "logout"
493
            String username = null;
494
            String password = null;
495
            String[] groupnames = null;
496
            String sess_id = null;
497
            name = null;
498
            
499
            // handle login action
500
            if (action.equals("login")) {
501
                PrintWriter out = response.getWriter();
502
                handleLoginAction(out, params, request, response);
503
                out.close();
504
        
505
                // handle logout action
506
            }   else if (action.equals("logout")) {
507
                PrintWriter out = response.getWriter();
508
                handleLogoutAction(out, params, request, response);
509
                out.close();
510

    
511
                // handle shrink DBConnection request
512
            } else if (action.equals("shrink")) {
513
                PrintWriter out = response.getWriter();
514
                boolean success = false;
515
                //If all DBConnection in the pool are free and DBConnection
516
                // pool
517
                //size is greater than initial value, shrink the connection
518
                // pool
519
                //size to initial value
520
                success = DBConnectionPool.shrinkConnectionPoolSize();
521
                if (success) {
522
                    //if successfully shrink the pool size to initial value
523
                    out.println("DBConnection Pool shrunk successfully.");
524
                }//if
525
                else {
526
                    out.println("DBConnection pool not shrunk successfully.");
527
                }
528
                //close out put
529
                out.close();
530

    
531
                // aware of session expiration on every request
532
            } else {
533
                HttpSession sess = request.getSession(true);
534
                if (sess.isNew() && !params.containsKey("sessionid")) {
535
                    // session expired or has not been stored b/w user requests
536
                    logMetacat.info(
537
                            "The session is new or no sessionid is assigned. The user is public");
538
                    username = "public";
539
                    sess.setAttribute("username", username);
540
                } else {
541
                    logMetacat.info("The session is either old or "
542
                            + "has sessionid parameter");
543
                    try {
544
                        if (params.containsKey("sessionid")) {
545
                            sess_id = ((String[]) params.get("sessionid"))[0];
546
                            logMetacat.info("in has sessionid "
547
                                    + sess_id);
548
                            if (sessionHash.containsKey(sess_id)) {
549
                                logMetacat.info("find the id "
550
                                        + sess_id + " in hash table");
551
                                sess = (HttpSession) sessionHash.get(sess_id);
552
                            }
553
                        } else {
554
                            // we already store the session in login, so we
555
                            // don't need here
556
                            /*
557
                             * logMetacat.info("in no sessionid
558
                             * parameter ", 40); sess_id =
559
                             * (String)sess.getId();
560
                             * logMetacat.info("storing the session id "
561
                             * + sess_id + " which has username " +
562
                             * sess.getAttribute("username") + " into session
563
                             * hash in handleGetOrPost method", 35);
564
                             */
565
                        }
566
                    } catch (IllegalStateException ise) {
567
                        logMetacat.error(
568
                                "Error in handleGetOrPost: this shouldn't "
569
                                + "happen: the session should be valid: "
570
                                + ise.getMessage());
571
                    }
572

    
573
                    username = (String) sess.getAttribute("username");
574
                    logMetacat.info("The user name from session is: "
575
                            + username);
576
                    password = (String) sess.getAttribute("password");
577
                    groupnames = (String[]) sess.getAttribute("groupnames");
578
                    name = (String) sess.getAttribute("name");
579
                }
580

    
581
                //make user user username should be public
582
                if (username == null || (username.trim().equals(""))) {
583
                    username = "public";
584
                }
585
                logMetacat.info("The user is : " + username);
586
            }
587
            // Now that we know the session is valid, we can delegate the
588
            // request
589
            // to a particular action handler
590
            if (action.equals("query")) {
591
                PrintWriter out = response.getWriter();
592
                handleQuery(out, params, response, username, groupnames,
593
                        sess_id);
594
                out.close();
595
            } else if (action.equals("squery")) {
596
                PrintWriter out = response.getWriter();
597
                if (params.containsKey("query")) {
598
                    handleSQuery(out, params, response, username, groupnames,
599
                            sess_id);
600
                    out.close();
601
                } else {
602
                    out.println(
603
                            "Illegal action squery without \"query\" parameter");
604
                    out.close();
605
                }
606
            } else if ( action.trim().equals("spatial_query")) {
607

    
608
              logMetacat.debug("******************* SPATIAL QUERY ********************");
609
              PrintWriter out = response.getWriter();
610
              handleSpatialQuery(out, params, response, username, groupnames, sess_id);
611
              out.close();
612
            
613
            } else if (action.equals("export")) {
614

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

    
771
            //util.closeConnections();
772
            // Close the stream to the client
773
            //out.close();
774
        }
775
    }
776

    
777
    /////////////////////////////// METACAT SPATIAL ///////////////////////////
778

    
779
    /**
780
     * handles all spatial queries -- these queries may include any of the 
781
     * queries supported by the WFS / WMS standards
782
     * 
783
     * handleSQuery(out, params, response, username, groupnames,
784
     *                        sess_id);
785
     */
786
    private void handleSpatialQuery(PrintWriter out, Hashtable params, 
787
                                    HttpServletResponse response,
788
                                    String username, String[] groupnames, 
789
                                    String sess_id) {
790
      
791
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
792

    
793
	if ( !MetaCatUtil.getOption("runSpatialOption").equals("true") ) {
794
        	response.setContentType("text/html");
795
        	out.println("<html> Metacat Spatial Option is turned off </html>");
796
        	out.close();
797
		return ;
798
	}		
799
      
800
        /* 
801
         * Perform spatial query against spatial cache
802
         */
803
        Float _xmax = Float.parseFloat( ((String[]) params.get("XMAX"))[0] );
804
        Float _ymax = Float.parseFloat( ((String[]) params.get("YMAX"))[0] );
805
        Float _xmin = Float.parseFloat( ((String[]) params.get("XMIN"))[0] );
806
        Float _ymin = Float.parseFloat( ((String[]) params.get("YMIN"))[0] );
807
        SpatialQuery sq = new SpatialQuery();
808
        Vector docids = sq.filterByBbox( _xmin, _ymin, _xmax, _ymax );
809
        logMetacat.info(" --- Spatial Query completed. Passing on the SQuery handler");
810

    
811
        /*
812
         * Create an array matching docids
813
         */
814
        String [] docidArray = new String[docids.size()];
815
        docids.toArray(docidArray);
816

    
817
        /*
818
         * Create squery string
819
         */
820
        String squery = DocumentIdQuery.createDocidQuery( docidArray );
821
        logMetacat.info("-----------\n" + squery + "\n------------------");
822
        String[] queryArray = new String[1];
823
        queryArray[0] = squery;
824
        params.put("query", queryArray);
825

    
826
        /*
827
         * Determine qformat
828
         */
829
        String[] qformatArray = new String[1];
830
        try {
831
            String _skin = ((String[]) params.get("SKIN"))[0];
832
            qformatArray[0] = _skin;
833
        } catch (java.lang.NullPointerException e) {
834
            // should be "default" but keep this for backwards compatibility with knp site
835
            logMetacat.warn("No SKIN specified for metacat actions=spatial_query... defaulting to 'knp' skin !\n");
836
            qformatArray[0] = "knp";
837
        }
838
        params.put("qformat", qformatArray);
839

    
840
        // change the action
841
        String[] actionArray = new String[1];
842
        actionArray[0] = "squery";
843
        params.put("action", actionArray);
844

    
845
        /*
846
         * Pass the docids to the DBQuery contructor
847
         */
848
        DBQuery queryobj = new DBQuery(docids);
849
        queryobj.findDocuments(response, out, params, username, groupnames, sess_id);
850

    
851
  }
852

    
853
    // LOGIN & LOGOUT SECTION
854
    /**
855
     * Handle the login request. Create a new session object. Do user
856
     * authentication through the session.
857
     */
858
    private void handleLoginAction(PrintWriter out, Hashtable params,
859
            HttpServletRequest request, HttpServletResponse response)
860
    {
861
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
862
        AuthSession sess = null;
863

    
864
        if(params.get("username") == null){
865
            response.setContentType("text/xml");
866
            out.println("<?xml version=\"1.0\"?>");
867
            out.println("<error>");
868
            out.println("Username not specified");
869
            out.println("</error>");
870
            return;
871
        }
872

    
873
        //}
874

    
875
        if(params.get("password") == null){
876
            response.setContentType("text/xml");
877
            out.println("<?xml version=\"1.0\"?>");
878
            out.println("<error>");
879
            out.println("Password not specified");
880
            out.println("</error>");
881
            return;
882
        }
883

    
884
        String un = ((String[]) params.get("username"))[0];
885
        logMetacat.info("user " + un + " is trying to login");
886
        String pw = ((String[]) params.get("password"))[0];
887

    
888
        String qformat = "xml";
889
        if(params.get("qformat") != null){
890
            qformat = ((String[]) params.get("qformat"))[0];
891
        }
892

    
893
        try {
894
            sess = new AuthSession();
895
        } catch (Exception e) {
896
            System.out.println("error in MetacatServlet.handleLoginAction: "
897
                    + e.getMessage());
898
            out.println(e.getMessage());
899
            return;
900
        }
901
        boolean isValid = sess.authenticate(request, un, pw);
902

    
903
        //if it is authernticate is true, store the session
904
        if (isValid) {
905
            HttpSession session = sess.getSessions();
906
            String id = session.getId();
907
            logMetacat.info("Store session id " + id
908
                    + "which has username" + session.getAttribute("username")
909
                    + " into hash in login method");
910
            sessionHash.put(id, session);
911
        }
912

    
913
        // format and transform the output
914
        if (qformat.equals("xml")) {
915
            response.setContentType("text/xml");
916
            out.println(sess.getMessage());
917
        } else {
918
            try {
919
                DBTransform trans = new DBTransform();
920
                response.setContentType("text/html");
921
                trans.transformXMLDocument(sess.getMessage(),
922
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
923
                        out, null);
924
            } catch (Exception e) {
925

    
926
                logMetacat.error(
927
                        "Error in MetaCatServlet.handleLoginAction: "
928
                                + e.getMessage());
929
            }
930
        }
931
    }
932

    
933
    /**
934
     * Handle the logout request. Close the connection.
935
     */
936
    private void handleLogoutAction(PrintWriter out, Hashtable params,
937
            HttpServletRequest request, HttpServletResponse response)
938
    {
939
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
940
        String qformat = "xml";
941
        if(params.get("qformat") != null){
942
            qformat = ((String[]) params.get("qformat"))[0];
943
        }
944

    
945
        // close the connection
946
        HttpSession sess = request.getSession(false);
947
        logMetacat.info("After get session in logout request");
948
        if (sess != null) {
949
            logMetacat.info("The session id " + sess.getId()
950
                    + " will be invalidate in logout action");
951
            logMetacat.info("The session contains user "
952
                    + sess.getAttribute("username")
953
                    + " will be invalidate in logout action");
954
            sess.invalidate();
955
        }
956

    
957
        // produce output
958
        StringBuffer output = new StringBuffer();
959
        output.append("<?xml version=\"1.0\"?>");
960
        output.append("<logout>");
961
        output.append("User logged out");
962
        output.append("</logout>");
963

    
964
        //format and transform the output
965
        if (qformat.equals("xml")) {
966
            response.setContentType("text/xml");
967
            out.println(output.toString());
968
        } else {
969
            try {
970
                DBTransform trans = new DBTransform();
971
                response.setContentType("text/html");
972
                trans.transformXMLDocument(output.toString(),
973
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
974
                        out, null);
975
            } catch (Exception e) {
976
                logMetacat.error(
977
                        "Error in MetaCatServlet.handleLogoutAction"
978
                                + e.getMessage());
979
            }
980
        }
981
    }
982

    
983
    // END OF LOGIN & LOGOUT SECTION
984

    
985
    // SQUERY & QUERY SECTION
986
    /**
987
     * Retreive the squery xml, execute it and display it
988
     *
989
     * @param out the output stream to the client
990
     * @param params the Hashtable of parameters that should be included in the
991
     *            squery.
992
     * @param response the response object linked to the client
993
     * @param conn the database connection
994
     */
995
    private void handleSQuery(PrintWriter out, Hashtable params,
996
            HttpServletResponse response, String user, String[] groups,
997
            String sessionid)
998
    {
999
        double startTime = System.currentTimeMillis() / 1000;
1000
        DBQuery queryobj = new DBQuery();
1001
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
1002
        double outPutTime = System.currentTimeMillis() / 1000;
1003
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1004
        logMetacat.info("Total search time for action 'squery': "
1005
                + (outPutTime - startTime));
1006
    }
1007

    
1008
    /**
1009
     * Create the xml query, execute it and display the results.
1010
     *
1011
     * @param out the output stream to the client
1012
     * @param params the Hashtable of parameters that should be included in the
1013
     *            squery.
1014
     * @param response the response object linked to the client
1015
     */
1016
    private void handleQuery(PrintWriter out, Hashtable params,
1017
            HttpServletResponse response, String user, String[] groups,
1018
            String sessionid)
1019
    {
1020
        //create the query and run it
1021
        String xmlquery = DBQuery.createSQuery(params);
1022
        String[] queryArray = new String[1];
1023
        queryArray[0] = xmlquery;
1024
        params.put("query", queryArray);
1025
        double startTime = System.currentTimeMillis() / 1000;
1026
        DBQuery queryobj = new DBQuery();
1027
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
1028
        double outPutTime = System.currentTimeMillis() / 1000;
1029
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1030
        logMetacat.info("Total search time for action 'query': "
1031
                + (outPutTime - startTime));
1032

    
1033
        //handleSQuery(out, params, response,user, groups, sessionid);
1034
    }
1035

    
1036
    // END OF SQUERY & QUERY SECTION
1037

    
1038
    //Exoport section
1039
    /**
1040
     * Handle the "export" request of data package from Metacat in zip format
1041
     *
1042
     * @param params the Hashtable of HTTP request parameters
1043
     * @param response the HTTP response object linked to the client
1044
     * @param user the username sent the request
1045
     * @param groups the user's groupnames
1046
     */
1047
    private void handleExportAction(Hashtable params,
1048
            HttpServletResponse response,
1049
            String user, String[] groups, String passWord)
1050
    {
1051
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1052
        // Output stream
1053
        ServletOutputStream out = null;
1054
        // Zip output stream
1055
        ZipOutputStream zOut = null;
1056
        DBQuery queryObj = null;
1057

    
1058
        String[] docs = new String[10];
1059
        String docId = "";
1060

    
1061
        try {
1062
            // read the params
1063
            if (params.containsKey("docid")) {
1064
                docs = (String[]) params.get("docid");
1065
            }
1066
            // Create a DBuery to handle export
1067
            queryObj = new DBQuery();
1068
            // Get the docid
1069
            docId = docs[0];
1070
            // Make sure the client specify docid
1071
            if (docId == null || docId.equals("")) {
1072
                response.setContentType("text/xml"); //MIME type
1073
                // Get a printwriter
1074
                PrintWriter pw = response.getWriter();
1075
                // Send back message
1076
                pw.println("<?xml version=\"1.0\"?>");
1077
                pw.println("<error>");
1078
                pw.println("You didn't specify requested docid");
1079
                pw.println("</error>");
1080
                // Close printwriter
1081
                pw.close();
1082
                return;
1083
            }
1084
            // Get output stream
1085
            out = response.getOutputStream();
1086
            response.setContentType("application/zip"); //MIME type
1087
            response.setHeader("Content-Disposition", 
1088
            		"attachment; filename=" 
1089
            		+ docId + ".zip"); // Set the name of the zip file
1090
            		
1091
            zOut = new ZipOutputStream(out);
1092
            zOut = queryObj
1093
                    .getZippedPackage(docId, out, user, groups, passWord);
1094
            zOut.finish(); //terminate the zip file
1095
            zOut.close(); //close the zip stream
1096

    
1097
        } catch (Exception e) {
1098
            try {
1099
                response.setContentType("text/xml"); //MIME type
1100
                // Send error message back
1101
                if (out != null) {
1102
                    PrintWriter pw = new PrintWriter(out);
1103
                    pw.println("<?xml version=\"1.0\"?>");
1104
                    pw.println("<error>");
1105
                    pw.println(e.getMessage());
1106
                    pw.println("</error>");
1107
                    // Close printwriter
1108
                    pw.close();
1109
                    // Close output stream
1110
                    out.close();
1111
                }
1112
                // Close zip output stream
1113
                if (zOut != null) {
1114
                    zOut.close();
1115
                }
1116
            } catch (IOException ioe) {
1117
                logMetacat.error("Problem with the servlet output "
1118
                        + "in MetacatServlet.handleExportAction: "
1119
                        + ioe.getMessage());
1120
            }
1121

    
1122
            logMetacat.error(
1123
                    "Error in MetacatServlet.handleExportAction: "
1124
                            + e.getMessage());
1125
            e.printStackTrace(System.out);
1126

    
1127
        }
1128

    
1129
    }
1130

    
1131
    /**
1132
     * In eml2 document, the xml can have inline data and data was stripped off
1133
     * and store in file system. This action can be used to read inline data
1134
     * only
1135
     *
1136
     * @param params the Hashtable of HTTP request parameters
1137
     * @param response the HTTP response object linked to the client
1138
     * @param user the username sent the request
1139
     * @param groups the user's groupnames
1140
     */
1141
    private void handleReadInlineDataAction(Hashtable params,
1142
            HttpServletRequest request, HttpServletResponse response,
1143
            String user, String passWord, String[] groups)
1144
    {
1145
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1146
        String[] docs = new String[10];
1147
        String inlineDataId = null;
1148
        String docId = "";
1149
        ServletOutputStream out = null;
1150

    
1151
        try {
1152
            // read the params
1153
            if (params.containsKey("inlinedataid")) {
1154
                docs = (String[]) params.get("inlinedataid");
1155
            }
1156
            // Get the docid
1157
            inlineDataId = docs[0];
1158
            // Make sure the client specify docid
1159
            if (inlineDataId == null || inlineDataId.equals("")) {
1160
                throw new Exception("You didn't specify requested inlinedataid"); }
1161

    
1162
            // check for permission
1163
            docId = MetaCatUtil
1164
                    .getDocIdWithoutRevFromInlineDataID(inlineDataId);
1165
            PermissionController controller = new PermissionController(docId);
1166
            // check top level read permission
1167
            if (!controller.hasPermission(user, groups,
1168
                    AccessControlInterface.READSTRING))
1169
            {
1170
                throw new Exception("User " + user
1171
                        + " doesn't have permission " + " to read document "
1172
                        + docId);
1173
            }
1174
            else
1175
            {
1176
              //check data access level
1177
              try
1178
              {
1179
                Hashtable unReadableInlineDataList =
1180
                    PermissionController.getUnReadableInlineDataIdList(docId,
1181
                    user, groups, false);
1182
                if (unReadableInlineDataList.containsValue(
1183
                          MetaCatUtil.getInlineDataIdWithoutRev(inlineDataId)))
1184
                {
1185
                  throw new Exception("User " + user
1186
                       + " doesn't have permission " + " to read inlinedata "
1187
                       + inlineDataId);
1188

    
1189
                }//if
1190
              }//try
1191
              catch (Exception e)
1192
              {
1193
                throw e;
1194
              }//catch
1195
            }//else
1196

    
1197
            // Get output stream
1198
            out = response.getOutputStream();
1199
            // read the inline data from the file
1200
            String inlinePath = MetaCatUtil.getOption("inlinedatafilepath");
1201
            File lineData = new File(inlinePath, inlineDataId);
1202
            FileInputStream input = new FileInputStream(lineData);
1203
            byte[] buffer = new byte[4 * 1024];
1204
            int bytes = input.read(buffer);
1205
            while (bytes != -1) {
1206
                out.write(buffer, 0, bytes);
1207
                bytes = input.read(buffer);
1208
            }
1209
            out.close();
1210

    
1211
            EventLog.getInstance().log(request.getRemoteAddr(), user,
1212
                    inlineDataId, "readinlinedata");
1213
        } catch (Exception e) {
1214
            try {
1215
                PrintWriter pw = null;
1216
                // Send error message back
1217
                if (out != null) {
1218
                    pw = new PrintWriter(out);
1219
                } else {
1220
                    pw = response.getWriter();
1221
                }
1222
                pw.println("<?xml version=\"1.0\"?>");
1223
                pw.println("<error>");
1224
                pw.println(e.getMessage());
1225
                pw.println("</error>");
1226
                // Close printwriter
1227
                pw.close();
1228
                // Close output stream if out is not null
1229
                if (out != null) {
1230
                    out.close();
1231
                }
1232
            } catch (IOException ioe) {
1233
                logMetacat.error("Problem with the servlet output "
1234
                        + "in MetacatServlet.handleExportAction: "
1235
                        + ioe.getMessage());
1236
            }
1237
            logMetacat.error(
1238
                    "Error in MetacatServlet.handleReadInlineDataAction: "
1239
                            + e.getMessage());
1240
        }
1241
    }
1242

    
1243
    /*
1244
     * Get the nodeid from xml_nodes for the inlinedataid
1245
     */
1246
    private long getInlineDataNodeId(String inLineDataId, String docId)
1247
            throws SQLException
1248
    {
1249
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1250
        long nodeId = 0;
1251
        String INLINE = "inline";
1252
        boolean hasRow;
1253
        PreparedStatement pStmt = null;
1254
        DBConnection conn = null;
1255
        int serialNumber = -1;
1256
        String sql = "SELECT nodeid FROM xml_nodes WHERE docid=? AND nodedata=? "
1257
                + "AND nodetype='TEXT' AND parentnodeid IN "
1258
                + "(SELECT nodeid FROM xml_nodes WHERE docid=? AND "
1259
                + "nodetype='ELEMENT' AND nodename='" + INLINE + "')";
1260

    
1261
        try {
1262
            //check out DBConnection
1263
            conn = DBConnectionPool
1264
                    .getDBConnection("AccessControlList.isAllowFirst");
1265
            serialNumber = conn.getCheckOutSerialNumber();
1266

    
1267
            pStmt = conn.prepareStatement(sql);
1268
            //bind value
1269
            pStmt.setString(1, docId);//docid
1270
            pStmt.setString(2, inLineDataId);//inlinedataid
1271
            pStmt.setString(3, docId);
1272
            // excute query
1273
            pStmt.execute();
1274
            ResultSet rs = pStmt.getResultSet();
1275
            hasRow = rs.next();
1276
            // get result
1277
            if (hasRow) {
1278
                nodeId = rs.getLong(1);
1279
            }//if
1280

    
1281
        } catch (SQLException e) {
1282
            throw e;
1283
        } finally {
1284
            try {
1285
                pStmt.close();
1286
            } finally {
1287
                DBConnectionPool.returnDBConnection(conn, serialNumber);
1288
            }
1289
        }
1290
        logMetacat.debug("The nodeid for inlinedataid " + inLineDataId
1291
                + " is: " + nodeId);
1292
        return nodeId;
1293
    }
1294

    
1295
    /**
1296
     * Handle the "read" request of metadata/data files from Metacat or any
1297
     * files from Internet; transformed metadata XML document into HTML
1298
     * presentation if requested; zip files when more than one were requested.
1299
     *
1300
     * @param params the Hashtable of HTTP request parameters
1301
     * @param request the HTTP request object linked to the client
1302
     * @param response the HTTP response object linked to the client
1303
     * @param user the username sent the request
1304
     * @param groups the user's groupnames
1305
     */
1306
    private void handleReadAction(Hashtable params, HttpServletRequest request,
1307
            HttpServletResponse response, String user, String passWord,
1308
            String[] groups)
1309
    {
1310
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1311
        ServletOutputStream out = null;
1312
        ZipOutputStream zout = null;
1313
        PrintWriter pw = null;
1314
        boolean zip = false;
1315
        boolean withInlineData = true;
1316

    
1317
        try {
1318
            String[] docs = new String[0];
1319
            String docid = "";
1320
            String qformat = "";
1321
            String abstrpath = null;
1322

    
1323
            // read the params
1324
            if (params.containsKey("docid")) {
1325
                docs = (String[]) params.get("docid");
1326
            }
1327
            if (params.containsKey("qformat")) {
1328
                qformat = ((String[]) params.get("qformat"))[0];
1329
            }
1330
            // the param for only metadata (eml)
1331
            // we don't support read a eml document without inline data now.
1332
            /*if (params.containsKey("inlinedata")) {
1333

    
1334
                String inlineData = ((String[]) params.get("inlinedata"))[0];
1335
                if (inlineData.equalsIgnoreCase("false")) {
1336
                    withInlineData = false;
1337
                }
1338
            }*/
1339
            if ((docs.length > 1) || qformat.equals("zip")) {
1340
                zip = true;
1341
                out = response.getOutputStream();
1342
                response.setContentType("application/zip"); //MIME type
1343
                zout = new ZipOutputStream(out);
1344
            }
1345
            // go through the list of docs to read
1346
            for (int i = 0; i < docs.length; i++) {
1347
                try {
1348

    
1349
                    URL murl = new URL(docs[i]);
1350
                    Hashtable murlQueryStr = MetaCatUtil.parseQuery(
1351
                            murl.getQuery());
1352
                    // case docid="http://.../?docid=aaa"
1353
                    // or docid="metacat://.../?docid=bbb"
1354
                    if (murlQueryStr.containsKey("docid")) {
1355
                        // get only docid, eliminate the rest
1356
                        docid = (String) murlQueryStr.get("docid");
1357
                        if (zip) {
1358
                            addDocToZip(request, docid, zout, user, groups);
1359
                        } else {
1360
                            readFromMetacat(request, response, docid, qformat,
1361
                                    abstrpath, user, groups, zip, zout,
1362
                                    withInlineData, params);
1363
                        }
1364

    
1365
                        // case docid="http://.../filename"
1366
                    } else {
1367
                        docid = docs[i];
1368
                        if (zip) {
1369
                            addDocToZip(request, docid, zout, user, groups);
1370
                        } else {
1371
                            readFromURLConnection(response, docid);
1372
                        }
1373
                    }
1374

    
1375
                } catch (MalformedURLException mue) {
1376
                    docid = docs[i];
1377
                    if (zip) {
1378
                        addDocToZip(request, docid, zout, user, groups);
1379
                    } else {
1380
                        readFromMetacat(request, response, docid, qformat,
1381
                                abstrpath, user, groups, zip, zout,
1382
                                withInlineData, params);
1383
                    }
1384
                }
1385
            }
1386

    
1387
            if (zip) {
1388
                zout.finish(); //terminate the zip file
1389
                zout.close(); //close the zip stream
1390
            }
1391

    
1392
        } catch (McdbDocNotFoundException notFoundE) {
1393
            // To handle doc not found exception
1394
            // the docid which didn't be found
1395
            String notFoundDocId = notFoundE.getUnfoundDocId();
1396
            String notFoundRevision = notFoundE.getUnfoundRevision();
1397
            logMetacat.warn("Missed id: " + notFoundDocId);
1398
            logMetacat.warn("Missed rev: " + notFoundRevision);
1399
            try {
1400
                // read docid from remote server
1401
                readFromRemoteMetaCat(response, notFoundDocId,
1402
                        notFoundRevision, user, passWord, out, zip, zout);
1403
                // Close zout outputstream
1404
                if (zout != null) {
1405
                    zout.close();
1406
                }
1407
                // close output stream
1408
                if (out != null) {
1409
                    out.close();
1410
                }
1411

    
1412
            } catch (Exception exc) {
1413
                logMetacat.error(
1414
                        "Erorr in MetacatServlet.hanldReadAction: "
1415
                                + exc.getMessage());
1416
                try {
1417
                    if (out != null) {
1418
                        response.setContentType("text/xml");
1419
                        // Send back error message by printWriter
1420
                        pw = new PrintWriter(out);
1421
                        pw.println("<?xml version=\"1.0\"?>");
1422
                        pw.println("<error>");
1423
                        pw.println(notFoundE.getMessage());
1424
                        pw.println("</error>");
1425
                        pw.close();
1426
                        out.close();
1427

    
1428
                    } else {
1429
                        response.setContentType("text/xml"); //MIME type
1430
                        // Send back error message if out = null
1431
                        if (pw == null) {
1432
                            // If pw is null, open the respnose
1433
                            pw = response.getWriter();
1434
                        }
1435
                        pw.println("<?xml version=\"1.0\"?>");
1436
                        pw.println("<error>");
1437
                        pw.println(notFoundE.getMessage());
1438
                        pw.println("</error>");
1439
                        pw.close();
1440
                    }
1441
                    // close zout
1442
                    if (zout != null) {
1443
                        zout.close();
1444
                    }
1445
                } catch (IOException ie) {
1446
                    logMetacat.error("Problem with the servlet output "
1447
                            + "in MetacatServlet.handleReadAction: "
1448
                            + ie.getMessage());
1449
                }
1450
            }
1451
        } catch (Exception e) {
1452
            try {
1453

    
1454
                if (out != null) {
1455
                    response.setContentType("text/xml"); //MIME type
1456
                    pw = new PrintWriter(out);
1457
                    pw.println("<?xml version=\"1.0\"?>");
1458
                    pw.println("<error>");
1459
                    pw.println(e.getMessage());
1460
                    pw.println("</error>");
1461
                    pw.close();
1462
                    out.close();
1463
                } else {
1464
                    response.setContentType("text/xml"); //MIME type
1465
                    // Send back error message if out = null
1466
                    if (pw == null) {
1467
                        pw = response.getWriter();
1468
                    }
1469
                    pw.println("<?xml version=\"1.0\"?>");
1470
                    pw.println("<error>");
1471
                    pw.println(e.getMessage());
1472
                    pw.println("</error>");
1473
                    pw.close();
1474

    
1475
                }
1476
                // Close zip output stream
1477
                if (zout != null) {
1478
                    zout.close();
1479
                }
1480

    
1481
            } catch (IOException ioe) {
1482
                logMetacat.error("Problem with the servlet output "
1483
                        + "in MetacatServlet.handleReadAction: "
1484
                        + ioe.getMessage());
1485
                ioe.printStackTrace(System.out);
1486

    
1487
            }
1488

    
1489
            logMetacat.error(
1490
                    "Error in MetacatServlet.handleReadAction: "
1491
                            + e.getMessage());
1492
            //e.printStackTrace(System.out);
1493
        }
1494
    }
1495

    
1496
    /** read metadata or data from Metacat
1497
     */
1498
    private void readFromMetacat(HttpServletRequest request,
1499
            HttpServletResponse response, String docid, String qformat,
1500
            String abstrpath, String user, String[] groups, boolean zip,
1501
            ZipOutputStream zout, boolean withInlineData, Hashtable params)
1502
            throws ClassNotFoundException, IOException, SQLException,
1503
            McdbException, Exception
1504
    {
1505
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1506
        try {
1507
            
1508
            // here is hack for handle docid=john.10(in order to tell mike.jim.10.1
1509
            // mike.jim.10, we require to provide entire docid with rev). But
1510
            // some old client they only provide docid without rev, so we need
1511
            // to handle this suituation. First we will check how many
1512
            // seperator here, if only one, we will append the rev in xml_documents
1513
            // to the id.
1514
            docid = appendRev(docid);
1515
         
1516
            DocumentImpl doc = new DocumentImpl(docid);
1517

    
1518
            //check the permission for read
1519
            if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1520
                Exception e = new Exception("User " + user
1521
                        + " does not have permission"
1522
                        + " to read the document with the docid " + docid);
1523

    
1524
                throw e;
1525
            }
1526

    
1527
            if (doc.getRootNodeID() == 0) {
1528
                // this is data file
1529
                String filepath = MetaCatUtil.getOption("datafilepath");
1530
                if (!filepath.endsWith("/")) {
1531
                    filepath += "/";
1532
                }
1533
                String filename = filepath + docid;
1534
                FileInputStream fin = null;
1535
                fin = new FileInputStream(filename);
1536

    
1537
                //MIME type
1538
                String contentType = getServletContext().getMimeType(filename);
1539
                if (contentType == null) {
1540
                    ContentTypeProvider provider = new ContentTypeProvider(
1541
                            docid);
1542
                    contentType = provider.getContentType();
1543
                    logMetacat.info("Final contenttype is: "
1544
                            + contentType);
1545
                }
1546

    
1547
                response.setContentType(contentType);
1548
                // if we decide to use "application/octet-stream" for all data
1549
                // returns
1550
                // response.setContentType("application/octet-stream");
1551

    
1552
                try {
1553

    
1554
                    ServletOutputStream out = response.getOutputStream();
1555
                    byte[] buf = new byte[4 * 1024]; // 4K buffer
1556
                    int b = fin.read(buf);
1557
                    while (b != -1) {
1558
                        out.write(buf, 0, b);
1559
                        b = fin.read(buf);
1560
                    }
1561
                } finally {
1562
                    if (fin != null) fin.close();
1563
                }
1564

    
1565
            } else {
1566
                // this is metadata doc
1567
                if (qformat.equals("xml") || qformat.equals("")) {
1568
                    // if equals "", that means no qformat is specified. hence
1569
                    // by default the document should be returned in xml format
1570
                    // set content type first
1571
                    response.setContentType("text/xml"); //MIME type
1572
                    PrintWriter out = response.getWriter();
1573
                    doc.toXml(out, user, groups, withInlineData);
1574
                } else {
1575
                    response.setContentType("text/html"); //MIME type
1576
                    PrintWriter out = response.getWriter();
1577

    
1578
                    // Look up the document type
1579
                    String doctype = doc.getDoctype();
1580
                    // Transform the document to the new doctype
1581
                    DBTransform dbt = new DBTransform();
1582
                    dbt.transformXMLDocument(doc.toString(user, groups,
1583
                            withInlineData), doctype, "-//W3C//HTML//EN",
1584
                            qformat, out, params);
1585
                }
1586

    
1587
            }
1588
            EventLog.getInstance().log(request.getRemoteAddr(), user,
1589
                    docid, "read");
1590
        } catch (Exception except) {
1591
            throw except;
1592
        }
1593
    }
1594

    
1595
    /**
1596
     * read data from URLConnection
1597
     */
1598
    private void readFromURLConnection(HttpServletResponse response,
1599
            String docid) throws IOException, MalformedURLException
1600
    {
1601
        ServletOutputStream out = response.getOutputStream();
1602
        String contentType = getServletContext().getMimeType(docid); //MIME
1603
                                                                     // type
1604
        if (contentType == null) {
1605
            if (docid.endsWith(".xml")) {
1606
                contentType = "text/xml";
1607
            } else if (docid.endsWith(".css")) {
1608
                contentType = "text/css";
1609
            } else if (docid.endsWith(".dtd")) {
1610
                contentType = "text/plain";
1611
            } else if (docid.endsWith(".xsd")) {
1612
                contentType = "text/xml";
1613
            } else if (docid.endsWith("/")) {
1614
                contentType = "text/html";
1615
            } else {
1616
                File f = new File(docid);
1617
                if (f.isDirectory()) {
1618
                    contentType = "text/html";
1619
                } else {
1620
                    contentType = "application/octet-stream";
1621
                }
1622
            }
1623
        }
1624
        response.setContentType(contentType);
1625
        // if we decide to use "application/octet-stream" for all data returns
1626
        // response.setContentType("application/octet-stream");
1627

    
1628
        // this is http url
1629
        URL url = new URL(docid);
1630
        BufferedInputStream bis = null;
1631
        try {
1632
            bis = new BufferedInputStream(url.openStream());
1633
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1634
            int b = bis.read(buf);
1635
            while (b != -1) {
1636
                out.write(buf, 0, b);
1637
                b = bis.read(buf);
1638
            }
1639
        } finally {
1640
            if (bis != null) bis.close();
1641
        }
1642

    
1643
    }
1644

    
1645
    /**
1646
     * read file/doc and write to ZipOutputStream
1647
     *
1648
     * @param docid
1649
     * @param zout
1650
     * @param user
1651
     * @param groups
1652
     * @throws ClassNotFoundException
1653
     * @throws IOException
1654
     * @throws SQLException
1655
     * @throws McdbException
1656
     * @throws Exception
1657
     */
1658
    private void addDocToZip(HttpServletRequest request, String docid,
1659
            ZipOutputStream zout, String user, String[] groups) throws
1660
            ClassNotFoundException, IOException, SQLException, McdbException,
1661
            Exception
1662
    {
1663
        byte[] bytestring = null;
1664
        ZipEntry zentry = null;
1665

    
1666
        try {
1667
            URL url = new URL(docid);
1668

    
1669
            // this http url; read from URLConnection; add to zip
1670
            zentry = new ZipEntry(docid);
1671
            zout.putNextEntry(zentry);
1672
            BufferedInputStream bis = null;
1673
            try {
1674
                bis = new BufferedInputStream(url.openStream());
1675
                byte[] buf = new byte[4 * 1024]; // 4K buffer
1676
                int b = bis.read(buf);
1677
                while (b != -1) {
1678
                    zout.write(buf, 0, b);
1679
                    b = bis.read(buf);
1680
                }
1681
            } finally {
1682
                if (bis != null) bis.close();
1683
            }
1684
            zout.closeEntry();
1685

    
1686
        } catch (MalformedURLException mue) {
1687

    
1688
            // this is metacat doc (data file or metadata doc)
1689
            try {
1690
                DocumentImpl doc = new DocumentImpl(docid);
1691

    
1692
                //check the permission for read
1693
                if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1694
                    Exception e = new Exception("User " + user
1695
                            + " does not have "
1696
                            + "permission to read the document with the docid "
1697
                            + docid);
1698
                    throw e;
1699
                }
1700

    
1701
                if (doc.getRootNodeID() == 0) {
1702
                    // this is data file; add file to zip
1703
                    String filepath = MetaCatUtil.getOption("datafilepath");
1704
                    if (!filepath.endsWith("/")) {
1705
                        filepath += "/";
1706
                    }
1707
                    String filename = filepath + docid;
1708
                    FileInputStream fin = null;
1709
                    fin = new FileInputStream(filename);
1710
                    try {
1711

    
1712
                        zentry = new ZipEntry(docid);
1713
                        zout.putNextEntry(zentry);
1714
                        byte[] buf = new byte[4 * 1024]; // 4K buffer
1715
                        int b = fin.read(buf);
1716
                        while (b != -1) {
1717
                            zout.write(buf, 0, b);
1718
                            b = fin.read(buf);
1719
                        }
1720
                    } finally {
1721
                        if (fin != null) fin.close();
1722
                    }
1723
                    zout.closeEntry();
1724

    
1725
                } else {
1726
                    // this is metadata doc; add doc to zip
1727
                    bytestring = doc.toString().getBytes();
1728
                    zentry = new ZipEntry(docid + ".xml");
1729
                    zentry.setSize(bytestring.length);
1730
                    zout.putNextEntry(zentry);
1731
                    zout.write(bytestring, 0, bytestring.length);
1732
                    zout.closeEntry();
1733
                }
1734
                EventLog.getInstance().log(request.getRemoteAddr(), user,
1735
                        docid, "read");
1736
            } catch (Exception except) {
1737
                throw except;
1738
            }
1739
        }
1740
    }
1741

    
1742
    /**
1743
     * If metacat couldn't find a data file or document locally, it will read
1744
     * this docid from its home server. This is for the replication feature
1745
     */
1746
    private void readFromRemoteMetaCat(HttpServletResponse response,
1747
            String docid, String rev, String user, String password,
1748
            ServletOutputStream out, boolean zip, ZipOutputStream zout)
1749
            throws Exception
1750
    {
1751
        // Create a object of RemoteDocument, "" is for zipEntryPath
1752
        RemoteDocument remoteDoc = new RemoteDocument(docid, rev, user,
1753
                password, "");
1754
        String docType = remoteDoc.getDocType();
1755
        // Only read data file
1756
        if (docType.equals("BIN")) {
1757
            // If it is zip format
1758
            if (zip) {
1759
                remoteDoc.readDocumentFromRemoteServerByZip(zout);
1760
            } else {
1761
                if (out == null) {
1762
                    out = response.getOutputStream();
1763
                }
1764
                response.setContentType("application/octet-stream");
1765
                remoteDoc.readDocumentFromRemoteServer(out);
1766
            }
1767
        } else {
1768
            throw new Exception("Docid: " + docid + "." + rev
1769
                    + " couldn't find");
1770
        }
1771
    }
1772

    
1773
    /**
1774
     * Handle the database putdocument request and write an XML document to the
1775
     * database connection
1776
     */
1777
    private void handleInsertOrUpdateAction(HttpServletRequest request,
1778
            HttpServletResponse response, PrintWriter out, Hashtable params,
1779
            String user, String[] groups)
1780
    {
1781
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1782
        DBConnection dbConn = null;
1783
        int serialNumber = -1;
1784

    
1785
        if(params.get("docid") == null){
1786
            out.println("<?xml version=\"1.0\"?>");
1787
            out.println("<error>");
1788
            out.println("Docid not specified");
1789
            out.println("</error>");
1790
            logMetacat.error("Docid not specified");
1791
            return;
1792
        }
1793
        
1794
        if(!MetaCatUtil.canInsertOrUpdate(user, groups)){
1795
        	out.println("<?xml version=\"1.0\"?>");
1796
            out.println("<error>");
1797
            out.println("User '" + user + "' not allowed to insert and update");
1798
            out.println("</error>");
1799
            logMetacat.error("User '" + user + "' not allowed to insert and update");
1800
            return;
1801
        }
1802

    
1803
        try {
1804
            // Get the document indicated
1805
            String[] doctext = (String[]) params.get("doctext");
1806
            String pub = null;
1807
            if (params.containsKey("public")) {
1808
                pub = ((String[]) params.get("public"))[0];
1809
            }
1810

    
1811
            StringReader dtd = null;
1812
            if (params.containsKey("dtdtext")) {
1813
                String[] dtdtext = (String[]) params.get("dtdtext");
1814
                try {
1815
                    if (!dtdtext[0].equals("")) {
1816
                        dtd = new StringReader(dtdtext[0]);
1817
                    }
1818
                } catch (NullPointerException npe) {
1819
                }
1820
            }
1821

    
1822
            if(doctext == null){
1823
                out.println("<?xml version=\"1.0\"?>");
1824
                out.println("<error>");
1825
                out.println("Document text not submitted");
1826
                out.println("</error>");
1827
                return;
1828
            }
1829

    
1830
            StringReader xml = new StringReader(doctext[0]);
1831
            boolean validate = false;
1832
            DocumentImplWrapper documentWrapper = null;
1833
            try {
1834
                // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ...
1835
                // >
1836
                // in order to decide whether to use validation parser
1837
                validate = needDTDValidation(xml);
1838
                if (validate) {
1839
                    // set a dtd base validation parser
1840
                    String rule = DocumentImpl.DTD;
1841
                    documentWrapper = new DocumentImplWrapper(rule, validate);
1842
                } else {
1843

    
1844
                    String namespace = findNamespace(xml);
1845
                    
1846
                	if (namespace != null) {
1847
                		if (namespace.compareTo(DocumentImpl.EML2_0_0NAMESPACE) == 0
1848
                				|| namespace.compareTo(
1849
                				DocumentImpl.EML2_0_1NAMESPACE) == 0) {
1850
                			// set eml2 base	 validation parser
1851
                			String rule = DocumentImpl.EML200;
1852
                			// using emlparser to check id validation
1853
                			EMLParser parser = new EMLParser(doctext[0]);
1854
                			documentWrapper = new DocumentImplWrapper(rule, true);
1855
                		} else if (namespace.compareTo(
1856
                                DocumentImpl.EML2_1_0NAMESPACE) == 0) {
1857
                			// set eml2 base validation parser
1858
                			String rule = DocumentImpl.EML210;
1859
                			// using emlparser to check id validation
1860
                			EMLParser parser = new EMLParser(doctext[0]);
1861
                			documentWrapper = new DocumentImplWrapper(rule, true);
1862
                		} else {
1863
                			// set schema base validation parser
1864
                			String rule = DocumentImpl.SCHEMA;
1865
                			documentWrapper = new DocumentImplWrapper(rule, true);
1866
                		}
1867
                	} else {
1868
                		documentWrapper = new DocumentImplWrapper("", false);
1869
                	}
1870
                }
1871

    
1872
                String[] action = (String[]) params.get("action");
1873
                String[] docid = (String[]) params.get("docid");
1874
                String newdocid = null;
1875

    
1876
                String doAction = null;
1877
                if (action[0].equals("insert")) {
1878
                    doAction = "INSERT";
1879
                } else if (action[0].equals("update")) {
1880
                    doAction = "UPDATE";
1881
                }
1882

    
1883
                try {
1884
                    // get a connection from the pool
1885
                    dbConn = DBConnectionPool
1886
                            .getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1887
                    serialNumber = dbConn.getCheckOutSerialNumber();
1888

    
1889
                    // write the document to the database
1890
                    try {
1891
                        String accNumber = docid[0];
1892
                        logMetacat.debug("" + doAction + " "
1893
                                + accNumber + "...");
1894
                        if (accNumber.equals("")) {
1895
                            accNumber = null;
1896
                        }
1897
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1898
                                doAction, accNumber, user, groups);
1899
                        EventLog.getInstance().log(request.getRemoteAddr(),
1900
                                user, accNumber, action[0]);
1901
                    } catch (NullPointerException npe) {
1902
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1903
                                doAction, null, user, groups);
1904
                        EventLog.getInstance().log(request.getRemoteAddr(),
1905
                                user, "", action[0]);
1906
                    }
1907
                }
1908
                finally {
1909
                    // Return db connection
1910
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1911
                }
1912

    
1913
                // set content type and other response header fields first
1914
                //response.setContentType("text/xml");
1915
                out.println("<?xml version=\"1.0\"?>");
1916
                out.println("<success>");
1917
                out.println("<docid>" + newdocid + "</docid>");
1918
                out.println("</success>");
1919

    
1920
            } catch (NullPointerException npe) {
1921
                //response.setContentType("text/xml");
1922
                out.println("<?xml version=\"1.0\"?>");
1923
                out.println("<error>");
1924
                out.println(npe.getMessage());
1925
                out.println("</error>");
1926
                logMetacat.warn("Error in writing eml document to the database" + npe.getMessage());
1927
                npe.printStackTrace();
1928
            }
1929
        } catch (Exception e) {
1930
            //response.setContentType("text/xml");
1931
            out.println("<?xml version=\"1.0\"?>");
1932
            out.println("<error>");
1933
            out.println(e.getMessage());
1934
            out.println("</error>");
1935
            logMetacat.warn("Error in writing eml document to the database" + e.getMessage());
1936
            e.printStackTrace();
1937
        }
1938
    }
1939

    
1940
    /**
1941
     * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > in
1942
     * order to decide whether to use validation parser
1943
     */
1944
    private static boolean needDTDValidation(StringReader xmlreader)
1945
            throws IOException
1946
    {
1947
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1948
        StringBuffer cbuff = new StringBuffer();
1949
        java.util.Stack st = new java.util.Stack();
1950
        boolean validate = false;
1951
        int c;
1952
        int inx;
1953

    
1954
        // read from the stream until find the keywords
1955
        while ((st.empty() || st.size() < 4) && ((c = xmlreader.read()) != -1)) {
1956
            cbuff.append((char) c);
1957

    
1958
            // "<!DOCTYPE" keyword is found; put it in the stack
1959
            if ((inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1) {
1960
                cbuff = new StringBuffer();
1961
                st.push("<!DOCTYPE");
1962
            }
1963
            // "PUBLIC" keyword is found; put it in the stack
1964
            if ((inx = cbuff.toString().indexOf("PUBLIC")) != -1) {
1965
                cbuff = new StringBuffer();
1966
                st.push("PUBLIC");
1967
            }
1968
            // "SYSTEM" keyword is found; put it in the stack
1969
            if ((inx = cbuff.toString().indexOf("SYSTEM")) != -1) {
1970
                cbuff = new StringBuffer();
1971
                st.push("SYSTEM");
1972
            }
1973
            // ">" character is found; put it in the stack
1974
            // ">" is found twice: fisrt from <?xml ...?>
1975
            // and second from <!DOCTYPE ... >
1976
            if ((inx = cbuff.toString().indexOf(">")) != -1) {
1977
                cbuff = new StringBuffer();
1978
                st.push(">");
1979
            }
1980
        }
1981

    
1982
        // close the stream
1983
        xmlreader.reset();
1984

    
1985
        // check the stack whether it contains the keywords:
1986
        // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1987
        if (st.size() == 4) {
1988
            if (((String) st.pop()).equals(">")
1989
                    && (((String) st.peek()).equals("PUBLIC") | ((String) st
1990
                            .pop()).equals("SYSTEM"))
1991
                    && ((String) st.pop()).equals("<!DOCTYPE")) {
1992
                validate = true;
1993
            }
1994
        }
1995

    
1996
        logMetacat.info("Validation for dtd is " + validate);
1997
        return validate;
1998
    }
1999

    
2000
    // END OF INSERT/UPDATE SECTION
2001

    
2002
    /* check if the xml string contains key words to specify schema loocation */
2003
    private String findNamespace(StringReader xml) throws IOException
2004
    {
2005
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2006
        String namespace = null;
2007

    
2008
        String eml2_0_0NameSpace = DocumentImpl.EML2_0_0NAMESPACE;
2009
        String eml2_0_1NameSpace = DocumentImpl.EML2_0_1NAMESPACE;
2010
        String eml2_1_0NameSpace = DocumentImpl.EML2_1_0NAMESPACE;
2011

    
2012
        if (xml == null) {
2013
            logMetacat.debug("Validation for schema is "
2014
                    + namespace);
2015
            return namespace;
2016
        }
2017
        String targetLine = getSchemaLine(xml);
2018
		
2019
        if (targetLine != null) {
2020

    
2021
        	// find if the root element has prefix
2022
        	String prefix = getPrefix(targetLine);
2023
        	logMetacat.info("prefix is:" + prefix);
2024
        	int startIndex = 0;
2025
        	
2026
        	
2027
        	if(prefix != null)
2028
        	{
2029
        		// if prefix found then look for xmlns:prefix
2030
        		// element to find the ns 
2031
        		String namespaceWithPrefix = NAMESPACEKEYWORD 
2032
        					+ ":" + prefix;
2033
        		startIndex = targetLine.indexOf(namespaceWithPrefix);
2034
            	logMetacat.debug("namespaceWithPrefix is:" + namespaceWithPrefix+":");
2035
            	logMetacat.debug("startIndex is:" + startIndex);
2036
        		
2037
        	} else {
2038
        		// if prefix not found then look for xmlns
2039
        		// attribute to find the ns 
2040
        		startIndex = targetLine.indexOf(NAMESPACEKEYWORD);
2041
            	logMetacat.debug("startIndex is:" + startIndex);
2042
        	}
2043
        		
2044
            int start = 1;
2045
            int end = 1;
2046
            String namespaceString = null;
2047
            int count = 0;
2048
            if (startIndex != -1) {
2049
                for (int i = startIndex; i < targetLine.length(); i++) {
2050
                    if (targetLine.charAt(i) == '"') {
2051
                        count++;
2052
                    }
2053
                    if (targetLine.charAt(i) == '"' && count == 1) {
2054
                        start = i;
2055
                    }
2056
                    if (targetLine.charAt(i) == '"' && count == 2) {
2057
                        end = i;
2058
                        break;
2059
                    }
2060
                }
2061
            } 
2062
            // else: xmlns not found. namespace = null will be returned
2063

    
2064
         	logMetacat.debug("targetLine is " + targetLine);
2065
         	logMetacat.debug("start is " + end);
2066
         	logMetacat.debug("end is " + end);
2067
           
2068
            if(start < end){
2069
            	namespaceString = targetLine.substring(start + 1, end);
2070
            	logMetacat.debug("namespaceString is " + namespaceString);
2071
            }
2072
            logMetacat.debug("namespace in xml is: "
2073
                    + namespaceString);
2074
            if(namespaceString != null){
2075
            	if (namespaceString.indexOf(eml2_0_0NameSpace) != -1) {
2076
            		namespace = eml2_0_0NameSpace;
2077
            	} else if (namespaceString.indexOf(eml2_0_1NameSpace) != -1) {
2078
            		namespace = eml2_0_1NameSpace;
2079
            	} else if (namespaceString.indexOf(eml2_1_0NameSpace) != -1) {
2080
            		namespace = eml2_1_0NameSpace;
2081
            	} else {
2082
            		namespace = namespaceString;
2083
            	}
2084
            }
2085
        }
2086

    
2087
        logMetacat.debug("Validation for eml is " + namespace);
2088

    
2089
        return namespace;
2090

    
2091
    }
2092

    
2093
    private String getSchemaLine(StringReader xml) throws IOException
2094
    {
2095
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2096
        // find the line
2097
        String secondLine = null;
2098
        int count = 0;
2099
        int endIndex = 0;
2100
        int startIndex = 0;
2101
        final int TARGETNUM = 1;
2102
        StringBuffer buffer = new StringBuffer();
2103
        boolean comment = false;
2104
        boolean processingInstruction = false;
2105
        char thirdPreviousCharacter = '?';
2106
        char secondPreviousCharacter = '?';
2107
        char previousCharacter = '?';
2108
        char currentCharacter = '?';
2109
        int tmp = xml.read();
2110
        while (tmp != -1) {
2111
            currentCharacter = (char)tmp;
2112
            //in a comment
2113
            if (currentCharacter == '-' && previousCharacter == '-'
2114
                    && secondPreviousCharacter == '!'
2115
                    && thirdPreviousCharacter == '<') {
2116
                comment = true;
2117
            }
2118
            //out of comment
2119
            if (comment && currentCharacter == '>' && previousCharacter == '-'
2120
                    && secondPreviousCharacter == '-') {
2121
                comment = false;
2122
            }
2123

    
2124
            //in a processingInstruction
2125
            if (currentCharacter == '?' && previousCharacter == '<') {
2126
            	processingInstruction = true;
2127
            }
2128
            
2129
            //out of processingInstruction
2130
            if (processingInstruction && currentCharacter == '>' 
2131
            	&& previousCharacter == '?') {
2132
            	processingInstruction = false;
2133
            }
2134
            
2135
            //this is not comment or a processingInstruction
2136
            if (currentCharacter != '!' && previousCharacter == '<' 
2137
            	&& !comment && !processingInstruction) {
2138
                count++;
2139
            }
2140
            
2141
            // get target line
2142
            if (count == TARGETNUM && currentCharacter != '>') {
2143
                buffer.append(currentCharacter);
2144
            }
2145
            if (count == TARGETNUM && currentCharacter == '>') {
2146
                break;
2147
            }
2148
            thirdPreviousCharacter = secondPreviousCharacter;
2149
            secondPreviousCharacter = previousCharacter;
2150
            previousCharacter = currentCharacter;
2151
            tmp = xml.read();
2152
        }
2153
        secondLine = buffer.toString();
2154
        logMetacat.debug("the second line string is: " + secondLine);
2155
        
2156
        xml.reset();
2157
        return secondLine;
2158
    }
2159

    
2160
    private String getPrefix(String schemaLine)
2161
    {
2162
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2163
        String prefix = null;
2164
        
2165
        if(schemaLine.indexOf(" ") > 0){
2166
            String rootElement = "";
2167
            try {
2168
                rootElement = schemaLine.substring(0, schemaLine.indexOf(" "));
2169
            } catch (StringIndexOutOfBoundsException sioobe) {
2170
                rootElement = schemaLine;
2171
            }
2172

    
2173
            logMetacat.debug("rootElement:" + rootElement);
2174
        
2175
            if(rootElement.indexOf(":") > 0){
2176
                prefix = rootElement.substring(rootElement.indexOf(":") + 1,
2177
                    rootElement.length());
2178
            }
2179
            
2180
            if(prefix != null){
2181
                return prefix.trim();
2182
            }
2183
        }
2184
        return null;
2185
    }
2186

    
2187
    /**
2188
     * Handle the database delete request and delete an XML document from the
2189
     * database connection
2190
     */
2191
    private void handleDeleteAction(PrintWriter out, Hashtable params,
2192
            HttpServletRequest request, HttpServletResponse response,
2193
            String user, String[] groups)
2194
    {
2195
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2196
        String[] docid = (String[]) params.get("docid");
2197

    
2198
        if(docid == null){
2199
          response.setContentType("text/xml");
2200
          out.println("<?xml version=\"1.0\"?>");
2201
          out.println("<error>");
2202
          out.println("Docid not specified.");
2203
          out.println("</error>");
2204
          logMetacat.error("Docid not specified for the document to be deleted.");
2205
        } else {
2206

    
2207
            // delete the document from the database
2208
            try {
2209

    
2210
                try {
2211
                    // null means notify server is null
2212
                    DocumentImpl.delete(docid[0], user, groups, null);
2213
                    EventLog.getInstance().log(request.getRemoteAddr(),
2214
                                               user, docid[0], "delete");
2215
                    response.setContentType("text/xml");
2216
                    out.println("<?xml version=\"1.0\"?>");
2217
                    out.println("<success>");
2218
                    out.println("Document deleted.");
2219
                    out.println("</success>");
2220
                    logMetacat.info("Document deleted.");
2221

    
2222
                    // Delete from spatial cache
2223
                    SpatialHarvester sh = new SpatialHarvester();
2224
                    sh.addToDeleteQue( MetaCatUtil.getSmartDocId( docid[0] ) );
2225
                    sh.destroy();
2226

    
2227
                }
2228
                catch (AccessionNumberException ane) {
2229
                    response.setContentType("text/xml");
2230
                    out.println("<?xml version=\"1.0\"?>");
2231
                    out.println("<error>");
2232
                    //out.println("Error deleting document!!!");
2233
                    out.println(ane.getMessage());
2234
                    out.println("</error>");
2235
                    logMetacat.error("Document could not be deleted: " 
2236
                    		+ ane.getMessage());
2237
                }
2238
            }
2239
            catch (Exception e) {
2240
                response.setContentType("text/xml");
2241
                out.println("<?xml version=\"1.0\"?>");
2242
                out.println("<error>");
2243
                out.println(e.getMessage());
2244
                out.println("</error>");
2245
                logMetacat.error("Document could not be deleted: " 
2246
                		+ e.getMessage());
2247
            }
2248
        }
2249
    }
2250

    
2251
    /**
2252
     * Handle the validation request and return the results to the requestor
2253
     */
2254
    private void handleValidateAction(PrintWriter out, Hashtable params)
2255
    {
2256

    
2257
        // Get the document indicated
2258
        String valtext = null;
2259
        DBConnection dbConn = null;
2260
        int serialNumber = -1;
2261

    
2262
        try {
2263
            valtext = ((String[]) params.get("valtext"))[0];
2264
        } catch (Exception nullpe) {
2265

    
2266
            String docid = null;
2267
            try {
2268
                // Find the document id number
2269
                docid = ((String[]) params.get("docid"))[0];
2270

    
2271
                // Get the document indicated from the db
2272
                DocumentImpl xmldoc = new DocumentImpl(docid);
2273
                valtext = xmldoc.toString();
2274

    
2275
            } catch (NullPointerException npe) {
2276

    
2277
                out.println("<error>Error getting document ID: " + docid
2278
                        + "</error>");
2279
                //if ( conn != null ) { util.returnConnection(conn); }
2280
                return;
2281
            } catch (Exception e) {
2282

    
2283
                out.println(e.getMessage());
2284
            }
2285
        }
2286

    
2287
        try {
2288
            // get a connection from the pool
2289
            dbConn = DBConnectionPool
2290
                    .getDBConnection("MetaCatServlet.handleValidateAction");
2291
            serialNumber = dbConn.getCheckOutSerialNumber();
2292
            DBValidate valobj = new DBValidate(dbConn);
2293
            boolean valid = valobj.validateString(valtext);
2294

    
2295
            // set content type and other response header fields first
2296

    
2297
            out.println(valobj.returnErrors());
2298

    
2299
        } catch (NullPointerException npe2) {
2300
            // set content type and other response header fields first
2301

    
2302
            out.println("<error>Error validating document.</error>");
2303
        } catch (Exception e) {
2304

    
2305
            out.println(e.getMessage());
2306
        } finally {
2307
            // Return db connection
2308
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2309
        }
2310
    }
2311

    
2312
    /**
2313
     * Handle "getrevsionanddoctype" action Given a docid, return it's current
2314
     * revision and doctype from data base The output is String look like
2315
     * "rev;doctype"
2316
     */
2317
    private void handleGetRevisionAndDocTypeAction(PrintWriter out,
2318
            Hashtable params)
2319
    {
2320
        // To store doc parameter
2321
        String[] docs = new String[10];
2322
        // Store a single doc id
2323
        String givenDocId = null;
2324
        // Get docid from parameters
2325
        if (params.containsKey("docid")) {
2326
            docs = (String[]) params.get("docid");
2327
        }
2328
        // Get first docid form string array
2329
        givenDocId = docs[0];
2330

    
2331
        try {
2332
            // Make sure there is a docid
2333
            if (givenDocId == null || givenDocId.equals("")) { throw new Exception(
2334
                    "User didn't specify docid!"); }//if
2335

    
2336
            // Create a DBUtil object
2337
            DBUtil dbutil = new DBUtil();
2338
            // Get a rev and doctype
2339
            String revAndDocType = dbutil
2340
                    .getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
2341
            out.println(revAndDocType);
2342

    
2343
        } catch (Exception e) {
2344
            // Handle exception
2345
            out.println("<?xml version=\"1.0\"?>");
2346
            out.println("<error>");
2347
            out.println(e.getMessage());
2348
            out.println("</error>");
2349
        }
2350

    
2351
    }
2352

    
2353
    /**
2354
     * Handle "getaccesscontrol" action. Read Access Control List from db
2355
     * connection in XML format
2356
     */
2357
    private void handleGetAccessControlAction(PrintWriter out,
2358
            Hashtable params, HttpServletResponse response, String username,
2359
            String[] groupnames)
2360
    {
2361
        DBConnection dbConn = null;
2362
        int serialNumber = -1;
2363
        String docid = ((String[]) params.get("docid"))[0];
2364

    
2365
        try {
2366

    
2367
            // get connection from the pool
2368
            dbConn = DBConnectionPool
2369
                    .getDBConnection("MetaCatServlet.handleGetAccessControlAction");
2370
            serialNumber = dbConn.getCheckOutSerialNumber();
2371
            AccessControlList aclobj = new AccessControlList(dbConn);
2372
            String acltext = aclobj.getACL(docid, username, groupnames);
2373
            out.println(acltext);
2374

    
2375
        } catch (Exception e) {
2376
            out.println("<?xml version=\"1.0\"?>");
2377
            out.println("<error>");
2378
            out.println(e.getMessage());
2379
            out.println("</error>");
2380
        } finally {
2381
            // Retrun db connection to pool
2382
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2383
        }
2384
    }
2385

    
2386
    /**
2387
     * Handle the "getprincipals" action. Read all principals from
2388
     * authentication scheme in XML format
2389
     */
2390
    private void handleGetPrincipalsAction(PrintWriter out, String user,
2391
            String password)
2392
    {
2393
        try {
2394
            AuthSession auth = new AuthSession();
2395
            String principals = auth.getPrincipals(user, password);
2396
            out.println(principals);
2397

    
2398
        } catch (Exception e) {
2399
            out.println("<?xml version=\"1.0\"?>");
2400
            out.println("<error>");
2401
            out.println(e.getMessage());
2402
            out.println("</error>");
2403
        }
2404
    }
2405

    
2406
    /**
2407
     * Handle "getdoctypes" action. Read all doctypes from db connection in XML
2408
     * format
2409
     */
2410
    private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
2411
            HttpServletResponse response)
2412
    {
2413
        try {
2414
            DBUtil dbutil = new DBUtil();
2415
            String doctypes = dbutil.readDoctypes();
2416
            out.println(doctypes);
2417
        } catch (Exception e) {
2418
            out.println("<?xml version=\"1.0\"?>");
2419
            out.println("<error>");
2420
            out.println(e.getMessage());
2421
            out.println("</error>");
2422
        }
2423
    }
2424

    
2425
    /**
2426
     * Handle the "getdtdschema" action. Read DTD or Schema file for a given
2427
     * doctype from Metacat catalog system
2428
     */
2429
    private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
2430
            HttpServletResponse response)
2431
    {
2432

    
2433
        String doctype = null;
2434
        String[] doctypeArr = (String[]) params.get("doctype");
2435

    
2436
        // get only the first doctype specified in the list of doctypes
2437
        // it could be done for all doctypes in that list
2438
        if (doctypeArr != null) {
2439
            doctype = ((String[]) params.get("doctype"))[0];
2440
        }
2441

    
2442
        try {
2443
            DBUtil dbutil = new DBUtil();
2444
            String dtdschema = dbutil.readDTDSchema(doctype);
2445
            out.println(dtdschema);
2446

    
2447
        } catch (Exception e) {
2448
            out.println("<?xml version=\"1.0\"?>");
2449
            out.println("<error>");
2450
            out.println(e.getMessage());
2451
            out.println("</error>");
2452
        }
2453

    
2454
    }
2455

    
2456
    /**
2457
     * Handle the "getlastdocid" action. Get the latest docid with rev number
2458
     * from db connection in XML format
2459
     */
2460
    private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
2461
            HttpServletResponse response)
2462
    {
2463

    
2464
        String scope = ((String[]) params.get("scope"))[0];
2465
        if (scope == null) {
2466
            scope = ((String[]) params.get("username"))[0];
2467
        }
2468

    
2469
        try {
2470

    
2471
            DBUtil dbutil = new DBUtil();
2472
            String lastDocid = dbutil.getMaxDocid(scope);
2473
            out.println("<?xml version=\"1.0\"?>");
2474
            out.println("<lastDocid>");
2475
            out.println("  <scope>" + scope + "</scope>");
2476
            out.println("  <docid>" + lastDocid + "</docid>");
2477
            out.println("</lastDocid>");
2478

    
2479
        } catch (Exception e) {
2480
            out.println("<?xml version=\"1.0\"?>");
2481
            out.println("<error>");
2482
            out.println(e.getMessage());
2483
            out.println("</error>");
2484
        }
2485
    }
2486

    
2487
    /**
2488
     * Print a report from the event log based on filter parameters passed in
2489
     * from the web.
2490
     *
2491
     * @param params the parameters from the web request
2492
     * @param request the http request object for getting request details
2493
     * @param response the http response object for writing output
2494
     */
2495
    private void handleGetLogAction(Hashtable params, HttpServletRequest request,
2496
            HttpServletResponse response, String username, String[] groups)
2497
    {
2498
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2499
        try {
2500
            response.setContentType("text/xml");
2501
            PrintWriter out = response.getWriter();
2502

    
2503
            // Check that the user is authenticated as an administrator account
2504
            if (!MetaCatUtil.isAdministrator(username, groups)) {
2505
                out.print("<error>");
2506
                out.print("The user \"" + username +
2507
                        "\" is not authorized for this action.");
2508
                out.print("</error>");
2509
                return;
2510
            }
2511

    
2512
            // Get all of the parameters in the correct formats
2513
            String[] ipAddress = (String[])params.get("ipaddress");
2514
            String[] principal = (String[])params.get("principal");
2515
            String[] docid = (String[])params.get("docid");
2516
            String[] event = (String[])params.get("event");
2517
            String[] startArray = (String[]) params.get("start");
2518
            String[] endArray = (String[]) params.get("end");
2519
            String start = null;
2520
            String end = null;
2521
            if (startArray != null) {
2522
                start = startArray[0];
2523
            }
2524
            if (endArray != null) {
2525
                end = endArray[0];
2526
            }
2527
            Timestamp startDate = null;
2528
            Timestamp endDate = null;
2529
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
2530
            try {
2531
                if (start != null) {
2532
                    startDate = new Timestamp((format.parse(start)).getTime());
2533
                }
2534
                if (end != null) {
2535
                    endDate = new Timestamp((format.parse(end)).getTime());
2536
                }
2537
            } catch (ParseException e) {
2538
                System.out.println("Failed to created Timestamp from input.");
2539
            }
2540

    
2541
            // Request the report by passing the filter parameters
2542
            out.println(EventLog.getInstance().getReport(ipAddress, principal,
2543
                    docid, event, startDate, endDate));
2544
            out.close();
2545
        } catch (IOException e) {
2546
            logMetacat.error(
2547
                    "Could not open http response for writing: " + e.getMessage());
2548
        }
2549
    }
2550

    
2551
    /**
2552
     * Rebuild the index for one or more documents. If the docid parameter is
2553
     * provided, rebuild for just that one document or list of documents. If
2554
     * not, then rebuild the index for all documents in the xml_documents
2555
     * table.
2556
     *
2557
     * @param params the parameters from the web request
2558
     * @param request the http request object for getting request details
2559
     * @param response the http response object for writing output
2560
     * @param username the username of the authenticated user
2561
     */
2562
    private void handleBuildIndexAction(Hashtable params,
2563
            HttpServletRequest request, HttpServletResponse response,
2564
            String username, String[] groups)
2565
    {
2566
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2567
        
2568
        // Get all of the parameters in the correct formats
2569
        String[] docid = (String[])params.get("docid");
2570

    
2571
        // Rebuild the indices for appropriate documents
2572
        try {
2573
            response.setContentType("text/xml");
2574
            PrintWriter out = response.getWriter();
2575

    
2576
            // Check that the user is authenticated as an administrator account
2577
            if (!MetaCatUtil.isAdministrator(username, groups)) {
2578
                out.print("<error>");
2579
                out.print("The user \"" + username +
2580
                        "\" is not authorized for this action.");
2581
                out.print("</error>");
2582
                return;
2583
            }
2584

    
2585
            // Process the documents
2586
            out.println("<success>");
2587
            if (docid == null || docid.length == 0) {
2588
                // Process all of the documents
2589
                try {
2590
                    Vector documents = getDocumentList();
2591
                    Iterator it = documents.iterator();
2592
                    while (it.hasNext()) {
2593
                        String id = (String) it.next();
2594
                        buildDocumentIndex(id, out);
2595
                    }
2596
                } catch (SQLException se) {
2597
                    out.print("<error>");
2598
                    out.print(se.getMessage());
2599
                    out.println("</error>");
2600
                }
2601
            } else {
2602
                // Only process the requested documents
2603
                for (int i = 0; i < docid.length; i++) {
2604
                    buildDocumentIndex(docid[i], out);
2605
                }
2606
            }
2607
            out.println("</success>");
2608
            out.close();
2609
        } catch (IOException e) {
2610
            logMetacat.error(
2611
                    "Could not open http response for writing: "
2612
                    + e.getMessage());
2613
        }
2614
    }
2615

    
2616
    /**
2617
     * Build the index for one document by reading the document and
2618
     * calling its buildIndex() method.
2619
     *
2620
     * @param docid the document (with revision) to rebuild
2621
     * @param out the PrintWriter to which output is printed
2622
     */
2623
    private void buildDocumentIndex(String docid, PrintWriter out)
2624
    {
2625
        try {
2626
            DocumentImpl doc = new DocumentImpl(docid, false);
2627
            doc.buildIndex();
2628
            out.print("<docid>" + docid);
2629
            out.println("</docid>");
2630
        } catch (McdbException me) {
2631
            out.print("<error>");
2632
            out.print(me.getMessage());
2633
            out.println("</error>");
2634
        }
2635
    }
2636

    
2637
    /**
2638
     * Handle documents passed to metacat that are encoded using the
2639
     * "multipart/form-data" mime type. This is typically used for uploading
2640
     * data files which may be binary and large.
2641
     */
2642
    private void handleMultipartForm(HttpServletRequest request,
2643
            HttpServletResponse response)
2644
    {
2645
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2646
        PrintWriter out = null;
2647
        String action = null;
2648

    
2649
        // Parse the multipart form, and save the parameters in a Hashtable and
2650
        // save the FileParts in a hashtable
2651

    
2652
        Hashtable params = new Hashtable();
2653
        Hashtable fileList = new Hashtable();
2654
        int sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit")))
2655
                .intValue();
2656
        logMetacat.info(
2657
                "The size limit of uploaded data files is: " + sizeLimit);
2658

    
2659
        try {
2660
            MultipartParser mp = new MultipartParser(request,
2661
                    sizeLimit * 1024 * 1024);
2662
            Part part;
2663
            while ((part = mp.readNextPart()) != null) {
2664
                String name = part.getName();
2665

    
2666
                if (part.isParam()) {
2667
                    // it's a parameter part
2668
                    ParamPart paramPart = (ParamPart) part;
2669
                    String value = paramPart.getStringValue();
2670
                    params.put(name, value);
2671
                    if (name.equals("action")) {
2672
                        action = value;
2673
                    }
2674
                } else if (part.isFile()) {
2675
                    // it's a file part
2676
                    FilePart filePart = (FilePart) part;
2677
                    fileList.put(name, filePart);
2678

    
2679
                    // Stop once the first file part is found, otherwise going
2680
                    // onto the
2681
                    // next part prevents access to the file contents. So...for
2682
                    // upload
2683
                    // to work, the datafile must be the last part
2684
                    break;
2685
                }
2686
            }
2687
        } catch (IOException ioe) {
2688
            try {
2689
                out = response.getWriter();
2690
            } catch (IOException ioe2) {
2691
                logMetacat.fatal("Fatal Error: couldn't get response output stream.");
2692
            }
2693
            out.println("<?xml version=\"1.0\"?>");
2694
            out.println("<error>");
2695
            out.println("Error: problem reading multipart data.");
2696
            out.println("</error>");
2697
        }
2698

    
2699
        // Get the session information
2700
        String username = null;
2701
        String password = null;
2702
        String[] groupnames = null;
2703
        String sess_id = null;
2704

    
2705
        // be aware of session expiration on every request
2706
        HttpSession sess = request.getSession(true);
2707
        if (sess.isNew()) {
2708
            // session expired or has not been stored b/w user requests
2709
            username = "public";
2710
            sess.setAttribute("username", username);
2711
        } else {
2712
            username = (String) sess.getAttribute("username");
2713
            password = (String) sess.getAttribute("password");
2714
            groupnames = (String[]) sess.getAttribute("groupnames");
2715
            try {
2716
                sess_id = (String) sess.getId();
2717
            } catch (IllegalStateException ise) {
2718
                System.out
2719
                        .println("error in  handleMultipartForm: this shouldn't "
2720
                                + "happen: the session should be valid: "
2721
                                + ise.getMessage());
2722
            }
2723
        }
2724

    
2725
        // Get the out stream
2726
        try {
2727
            out = response.getWriter();
2728
        } catch (IOException ioe2) {
2729
            logMetacat.error("Fatal Error: couldn't get response "
2730
                    + "output stream.");
2731
        }
2732

    
2733
        if (action.equals("upload")) {
2734
            if (username != null && !username.equals("public")) {
2735
                handleUploadAction(request, out, params, fileList, username,
2736
                        groupnames);
2737
            } else {
2738

    
2739
                out.println("<?xml version=\"1.0\"?>");
2740
                out.println("<error>");
2741
                out.println("Permission denied for " + action);
2742
                out.println("</error>");
2743
            }
2744
        } else {
2745
            /*
2746
             * try { out = response.getWriter(); } catch (IOException ioe2) {
2747
             * System.err.println("Fatal Error: couldn't get response output
2748
             * stream.");
2749
             */
2750
            out.println("<?xml version=\"1.0\"?>");
2751
            out.println("<error>");
2752
            out.println(
2753
                    "Error: action not registered.  Please report this error.");
2754
            out.println("</error>");
2755
        }
2756
        out.close();
2757
    }
2758

    
2759
    /**
2760
     * Handle the upload action by saving the attached file to disk and
2761
     * registering it in the Metacat db
2762
     */
2763
    private void handleUploadAction(HttpServletRequest request,
2764
            PrintWriter out, Hashtable params, Hashtable fileList,
2765
            String username, String[] groupnames)
2766
    {
2767
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2768
        //PrintWriter out = null;
2769
        //Connection conn = null;
2770
        String action = null;
2771
        String docid = null;
2772

    
2773
        /*
2774
         * response.setContentType("text/xml"); try { out =
2775
         * response.getWriter(); } catch (IOException ioe2) {
2776
         * System.err.println("Fatal Error: couldn't get response output
2777
         * stream.");
2778
         */
2779

    
2780
        if (params.containsKey("docid")) {
2781
            docid = (String) params.get("docid");
2782
        }
2783

    
2784
        // Make sure we have a docid and datafile
2785
        if (docid != null && fileList.containsKey("datafile")) {
2786
            logMetacat.info("Uploading data docid: " + docid);
2787
            // Get a reference to the file part of the form
2788
            FilePart filePart = (FilePart) fileList.get("datafile");
2789
            String fileName = filePart.getFileName();
2790
            logMetacat.info("Uploading filename: " + fileName);
2791
            // Check if the right file existed in the uploaded data
2792
            if (fileName != null) {
2793

    
2794
                try {
2795
                    //logMetacat.info("Upload datafile " + docid
2796
                    // +"...", 10);
2797
                    //If document get lock data file grant
2798
                    if (DocumentImpl.getDataFileLockGrant(docid)) {
2799
                        // Save the data file to disk using "docid" as the name
2800
                        String datafilepath = MetaCatUtil.getOption("datafilepath");
2801
                        File dataDirectory = new File(datafilepath);
2802
                        dataDirectory.mkdirs();
2803
                        File newFile = null;
2804
                        long size = 0;
2805
                        try
2806
                        {
2807
                          newFile = new File(dataDirectory, docid);
2808
                          size = filePart.writeTo(newFile);
2809
                        
2810
//                        register the file in the database (which generates
2811
                          // an exception
2812
                          //if the docid is not acceptable or other untoward
2813
                          // things happen
2814
                          DocumentImpl.registerDocument(fileName, "BIN", docid,
2815
                                username, groupnames);
2816
                        }
2817
                        catch (Exception ee)
2818
                        {
2819
                           //detelte the file to create
2820
                            newFile.delete();
2821
                            throw ee;
2822
                        }
2823

    
2824
                        EventLog.getInstance().log(request.getRemoteAddr(),
2825
                                username, docid, "upload");
2826
                        // Force replication this data file
2827
                        // To data file, "insert" and update is same
2828
                        // The fourth parameter is null. Because it is
2829
                        // notification server
2830
                        // and this method is in MetaCatServerlet. It is
2831
                        // original command,
2832
                        // not get force replication info from another metacat
2833
                        ForceReplicationHandler frh = new ForceReplicationHandler(
2834
                                docid, "insert", false, null);
2835

    
2836
                        // set content type and other response header fields
2837
                        // first
2838
                        out.println("<?xml version=\"1.0\"?>");
2839
                        out.println("<success>");
2840
                        out.println("<docid>" + docid + "</docid>");
2841
                        out.println("<size>" + size + "</size>");
2842
                        out.println("</success>");
2843
                    }
2844

    
2845
                } catch (Exception e) {
2846
                    
2847
                    out.println("<?xml version=\"1.0\"?>");
2848
                    out.println("<error>");
2849
                    out.println(e.getMessage());
2850
                    out.println("</error>");
2851
                }
2852
            } else {
2853
                // the field did not contain a file
2854
                out.println("<?xml version=\"1.0\"?>");
2855
                out.println("<error>");
2856
                out.println("The uploaded data did not contain a valid file.");
2857
                out.println("</error>");
2858
            }
2859
        } else {
2860
            // Error bcse docid missing or file missing
2861
            out.println("<?xml version=\"1.0\"?>");
2862
            out.println("<error>");
2863
            out.println("The uploaded data did not contain a valid docid "
2864
                    + "or valid file.");
2865
            out.println("</error>");
2866
        }
2867
    }
2868

    
2869
    /*
2870
     * A method to handle set access action
2871
     */
2872
    private void handleSetAccessAction(PrintWriter out, Hashtable params,
2873
            String username)
2874
    {
2875
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2876
        String[] docList = null;
2877
        String[] principalList = null;
2878
        String[] permissionList = null;
2879
        String[] permTypeList = null;
2880
        String[] permOrderList = null;
2881
        String permission = null;
2882
        String permType = null;
2883
        String permOrder = null;
2884
        Vector errorList = new Vector();
2885
        String error = null;
2886
        Vector successList = new Vector();
2887
        String success = null;
2888

    
2889
        // Get parameters
2890
        if (params.containsKey("docid")) {
2891
            docList = (String[]) params.get("docid");
2892
        }
2893
        if (params.containsKey("principal")) {
2894
            principalList = (String[]) params.get("principal");
2895
        }
2896
        if (params.containsKey("permission")) {
2897
            permissionList = (String[]) params.get("permission");
2898

    
2899
        }
2900
        if (params.containsKey("permType")) {
2901
            permTypeList = (String[]) params.get("permType");
2902

    
2903
        }
2904
        if (params.containsKey("permOrder")) {
2905
            permOrderList = (String[]) params.get("permOrder");
2906

    
2907
        }
2908

    
2909
        // Make sure the parameter is not null
2910
        if (docList == null || principalList == null || permTypeList == null
2911
                || permissionList == null) {
2912
            error = "Please check your parameter list, it should look like: "
2913
                    + "?action=setaccess&docid=pipeline.1.1&principal=public"
2914
                    + "&permission=read&permType=allow&permOrder=allowFirst";
2915
            errorList.addElement(error);
2916
            outputResponse(successList, errorList, out);
2917
            return;
2918
        }
2919

    
2920
        // Only select first element for permission, type and order
2921
        permission = permissionList[0];
2922
        permType = permTypeList[0];
2923
        if (permOrderList != null) {
2924
            permOrder = permOrderList[0];
2925
        }
2926

    
2927
        // Get package doctype set
2928
        Vector packageSet = MetaCatUtil.getOptionList(MetaCatUtil
2929
                .getOption("packagedoctypeset"));
2930
        //debug
2931
        if (packageSet != null) {
2932
            for (int i = 0; i < packageSet.size(); i++) {
2933
                logMetacat.debug("doctype in package set: "
2934
                        + (String) packageSet.elementAt(i));
2935
            }
2936
        }
2937

    
2938
        // handle every accessionNumber
2939
        for (int i = 0; i < docList.length; i++) {
2940
            String accessionNumber = docList[i];
2941
            String owner = null;
2942
            String publicId = null;
2943
            // Get document owner and public id
2944
            try {
2945
                owner = getFieldValueForDoc(accessionNumber, "user_owner");
2946
                publicId = getFieldValueForDoc(accessionNumber, "doctype");
2947
            } catch (Exception e) {
2948
                logMetacat.error("Error in handleSetAccessAction: "
2949
                        + e.getMessage());
2950
                error = "Error in set access control for document - "
2951
                        + accessionNumber + e.getMessage();
2952
                errorList.addElement(error);
2953
                continue;
2954
            }
2955
            //check if user is the owner. Only owner can do owner
2956
            if (username == null || owner == null || !username.equals(owner)) {
2957
                error = "User - " + username
2958
                        + " does not have permission to set "
2959
                        + "access control for docid - " + accessionNumber;
2960
                errorList.addElement(error);
2961
                continue;
2962
            }
2963

    
2964
            // If docid publicid is BIN data file or other beta4, 6 package
2965
            // document
2966
            // we could not do set access control. Because we don't want
2967
            // inconsistent
2968
            // to its access docuemnt
2969
            if (publicId != null && packageSet != null
2970
                    && packageSet.contains(publicId)) {
2971
                error = "Could not set access control to document "
2972
                        + accessionNumber
2973
                        + "because it is in a pakcage and it has a access file for it";
2974
                errorList.addElement(error);
2975
                continue;
2976
            }
2977

    
2978
            // for every principle
2979
            for (int j = 0; j < principalList.length; j++) {
2980
                String principal = principalList[j];
2981
                try {
2982
                    //insert permission
2983
                    AccessControlForSingleFile accessControl = new AccessControlForSingleFile(
2984
                            accessionNumber, principal, permission, permType,
2985
                            permOrder);
2986
                    accessControl.insertPermissions();
2987
                    success = "Set access control to document "
2988
                            + accessionNumber + " successfully";
2989
                    successList.addElement(success);
2990
                } catch (Exception ee) {
2991
                    logMetacat.error(
2992
                            "Erorr in handleSetAccessAction2: "
2993
                                    + ee.getMessage());
2994
                    error = "Faild to set access control for document "
2995
                            + accessionNumber + " because " + ee.getMessage();
2996
                    errorList.addElement(error);
2997
                    continue;
2998
                }
2999
            }
3000
        }
3001
        outputResponse(successList, errorList, out);
3002
    }
3003

    
3004
    /*
3005
     * A method try to determin a docid's public id, if couldn't find null will
3006
     * be returned.
3007
     */
3008
    private String getFieldValueForDoc(String accessionNumber, String fieldName)
3009
            throws Exception
3010
    {
3011
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
3012
        if (accessionNumber == null || accessionNumber.equals("")
3013
                || fieldName == null || fieldName.equals("")) { throw new Exception(
3014
                "Docid or field name was not specified"); }
3015

    
3016
        PreparedStatement pstmt = null;
3017
        ResultSet rs = null;
3018
        String fieldValue = null;
3019
        String docId = null;
3020
        DBConnection conn = null;
3021
        int serialNumber = -1;
3022

    
3023
        // get rid of revision if access number has
3024
        docId = MetaCatUtil.getDocIdFromString(accessionNumber);
3025
        try {
3026
            //check out DBConnection
3027
            conn = DBConnectionPool
3028
                    .getDBConnection("MetaCatServlet.getPublicIdForDoc");
3029
            serialNumber = conn.getCheckOutSerialNumber();
3030
            pstmt = conn.prepareStatement("SELECT " + fieldName
3031
                    + " FROM xml_documents " + "WHERE docid = ? ");
3032

    
3033
            pstmt.setString(1, docId);
3034
            pstmt.execute();
3035
            rs = pstmt.getResultSet();
3036
            boolean hasRow = rs.next();
3037
            int perm = 0;
3038
            if (hasRow) {
3039
                fieldValue = rs.getString(1);
3040
            } else {
3041
                throw new Exception("Could not find document: "
3042
                        + accessionNumber);
3043
            }
3044
        } catch (Exception e) {
3045
            logMetacat.error(
3046
                    "Exception in MetacatServlet.getPublicIdForDoc: "
3047
                            + e.getMessage());
3048
            throw e;
3049
        } finally {
3050
            try {
3051
                rs.close();
3052
                pstmt.close();
3053

    
3054
            } finally {
3055
                DBConnectionPool.returnDBConnection(conn, serialNumber);
3056
            }
3057
        }
3058
        return fieldValue;
3059
    }
3060

    
3061
    /*
3062
     * Get the list of documents from the database and return the list in an
3063
     * Vector of identifiers.
3064
     *
3065
     * @ returns the array of identifiers
3066
     */
3067
    private Vector getDocumentList() throws SQLException
3068
    {
3069
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
3070
        Vector docList = new Vector();
3071
        PreparedStatement pstmt = null;
3072
        ResultSet rs = null;
3073
        DBConnection conn = null;
3074
        int serialNumber = -1;
3075

    
3076
        try {
3077
            //check out DBConnection
3078
            conn = DBConnectionPool
3079
                    .getDBConnection("MetaCatServlet.getDocumentList");
3080
            serialNumber = conn.getCheckOutSerialNumber();
3081
            pstmt = conn.prepareStatement("SELECT docid, rev"
3082
                    + " FROM xml_documents ");
3083
            pstmt.execute();
3084
            rs = pstmt.getResultSet();
3085
            while (rs.next()) {
3086
                String docid = rs.getString(1);
3087
                String rev = rs.getString(2);
3088
                docList.add(docid + "." + rev);
3089
            }
3090
        } catch (SQLException e) {
3091
            logMetacat.error(
3092
                    "Exception in MetacatServlet.getDocumentList: "
3093
                            + e.getMessage());
3094
            throw e;
3095
        } finally {
3096
            try {
3097
                rs.close();
3098
                pstmt.close();
3099

    
3100
            } catch (SQLException se) {
3101
                logMetacat.error(
3102
                    "Exception in MetacatServlet.getDocumentList: "
3103
                            + se.getMessage());
3104
                throw se;
3105
            } finally {
3106
                DBConnectionPool.returnDBConnection(conn, serialNumber);
3107
            }
3108
        }
3109
        return docList;
3110
    }
3111

    
3112
    /*
3113
     * A method to output setAccess action result
3114
     */
3115
    private void outputResponse(Vector successList, Vector errorList,
3116
            PrintWriter out)
3117
    {
3118
        boolean error = false;
3119
        boolean success = false;
3120
        // Output prolog
3121
        out.println(PROLOG);
3122
        // output success message
3123
        if (successList != null) {
3124
            for (int i = 0; i < successList.size(); i++) {
3125
                out.println(SUCCESS);
3126
                out.println((String) successList.elementAt(i));
3127
                out.println(SUCCESSCLOSE);
3128
                success = true;
3129
            }
3130
        }
3131
        // output error message
3132
        if (errorList != null) {
3133
            for (int i = 0; i < errorList.size(); i++) {
3134
                out.println(ERROR);
3135
                out.println((String) errorList.elementAt(i));
3136
                out.println(ERRORCLOSE);
3137
                error = true;
3138
            }
3139
        }
3140

    
3141
        // if no error and no success info, send a error that nothing happened
3142
        if (!error && !success) {
3143
            out.println(ERROR);
3144
            out.println("Nothing happend for setaccess action");
3145
            out.println(ERRORCLOSE);
3146
        }
3147
    }
3148
    
3149
    /**
3150
     * Method to get session table which store the session info
3151
     * @return
3152
     */
3153
    public static Hashtable getSessionHash()
3154
    {
3155
        return sessionHash;
3156
    }
3157
    
3158
    /*
3159
     * If the given docid only have one seperter, we need 
3160
     * append rev for it. The rev come from xml_documents
3161
     */
3162
    private static String appendRev(String docid) throws Exception
3163
    {
3164
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
3165
        String newAccNum = null;
3166
        String separator = MetaCatUtil.getOption("accNumSeparator");
3167
        int firstIndex = docid.indexOf(separator);
3168
        int lastIndex = docid.lastIndexOf(separator);
3169
        if (firstIndex == lastIndex)
3170
        {
3171
            
3172
           //only one seperater
3173
            int rev = DBUtil.getLatestRevisionInDocumentTable(docid);
3174
            if (rev == -1)
3175
            {
3176
                throw new Exception("the requested docid '"
3177
                        + docid+ "' does not exist");
3178
            }
3179
            else
3180
            {
3181
                newAccNum = docid+ separator+ rev;
3182
            }
3183
        }
3184
        else
3185
        {
3186
            // in other suituation we don't change the docid
3187
            newAccNum = docid;
3188
        }
3189
        //logMetacat.debug("The docid will be read is "+newAccNum);
3190
        return newAccNum;
3191
  }
3192
}
(44-44/65)