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-10-04 14:44:38 -0700 (Wed, 04 Oct 2006) $'
11
 * '$Revision: 3055 $'
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
        logMetacat.warn("\n\n ******* after spatial query, we've got " + docids.size() + " docids \n\n");
811

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

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

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

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

    
846
        /*
847
         * Pass the docids to the DBQuery contructor
848
         */
849
        // This is a hack to get the empty result set to show...
850
        // Otherwise dbquery sees no docidOverrides and does a full % percent query
851
        if (docids.size() == 0)
852
            docids.add("");
853

    
854
        DBQuery queryobj = new DBQuery(docids);
855
        queryobj.findDocuments(response, out, params, username, groupnames, sess_id);
856

    
857
  }
858

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

    
870
        if(params.get("username") == null){
871
            response.setContentType("text/xml");
872
            out.println("<?xml version=\"1.0\"?>");
873
            out.println("<error>");
874
            out.println("Username not specified");
875
            out.println("</error>");
876
            return;
877
        }
878

    
879
        //}
880

    
881
        if(params.get("password") == null){
882
            response.setContentType("text/xml");
883
            out.println("<?xml version=\"1.0\"?>");
884
            out.println("<error>");
885
            out.println("Password not specified");
886
            out.println("</error>");
887
            return;
888
        }
889

    
890
        String un = ((String[]) params.get("username"))[0];
891
        logMetacat.info("user " + un + " is trying to login");
892
        String pw = ((String[]) params.get("password"))[0];
893

    
894
        String qformat = "xml";
895
        if(params.get("qformat") != null){
896
            qformat = ((String[]) params.get("qformat"))[0];
897
        }
898

    
899
        try {
900
            sess = new AuthSession();
901
        } catch (Exception e) {
902
            System.out.println("error in MetacatServlet.handleLoginAction: "
903
                    + e.getMessage());
904
            out.println(e.getMessage());
905
            return;
906
        }
907
        boolean isValid = sess.authenticate(request, un, pw);
908

    
909
        //if it is authernticate is true, store the session
910
        if (isValid) {
911
            HttpSession session = sess.getSessions();
912
            String id = session.getId();
913
            logMetacat.info("Store session id " + id
914
                    + "which has username" + session.getAttribute("username")
915
                    + " into hash in login method");
916
            sessionHash.put(id, session);
917
        }
918

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

    
932
                logMetacat.error(
933
                        "Error in MetaCatServlet.handleLoginAction: "
934
                                + e.getMessage());
935
            }
936
        }
937
    }
938

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

    
951
        // close the connection
952
        HttpSession sess = request.getSession(false);
953
        logMetacat.info("After get session in logout request");
954
        if (sess != null) {
955
            logMetacat.info("The session id " + sess.getId()
956
                    + " will be invalidate in logout action");
957
            logMetacat.info("The session contains user "
958
                    + sess.getAttribute("username")
959
                    + " will be invalidate in logout action");
960
            sess.invalidate();
961
        }
962

    
963
        // produce output
964
        StringBuffer output = new StringBuffer();
965
        output.append("<?xml version=\"1.0\"?>");
966
        output.append("<logout>");
967
        output.append("User logged out");
968
        output.append("</logout>");
969

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

    
989
    // END OF LOGIN & LOGOUT SECTION
990

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

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

    
1039
        //handleSQuery(out, params, response,user, groups, sessionid);
1040
    }
1041

    
1042
    // END OF SQUERY & QUERY SECTION
1043

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

    
1064
        String[] docs = new String[10];
1065
        String docId = "";
1066

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

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

    
1128
            logMetacat.error(
1129
                    "Error in MetacatServlet.handleExportAction: "
1130
                            + e.getMessage());
1131
            e.printStackTrace(System.out);
1132

    
1133
        }
1134

    
1135
    }
1136

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

    
1157
        try {
1158
            // read the params
1159
            if (params.containsKey("inlinedataid")) {
1160
                docs = (String[]) params.get("inlinedataid");
1161
            }
1162
            // Get the docid
1163
            inlineDataId = docs[0];
1164
            // Make sure the client specify docid
1165
            if (inlineDataId == null || inlineDataId.equals("")) {
1166
                throw new Exception("You didn't specify requested inlinedataid"); }
1167

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

    
1195
                }//if
1196
              }//try
1197
              catch (Exception e)
1198
              {
1199
                throw e;
1200
              }//catch
1201
            }//else
1202

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

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

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

    
1267
        try {
1268
            //check out DBConnection
1269
            conn = DBConnectionPool
1270
                    .getDBConnection("AccessControlList.isAllowFirst");
1271
            serialNumber = conn.getCheckOutSerialNumber();
1272

    
1273
            pStmt = conn.prepareStatement(sql);
1274
            //bind value
1275
            pStmt.setString(1, docId);//docid
1276
            pStmt.setString(2, inLineDataId);//inlinedataid
1277
            pStmt.setString(3, docId);
1278
            // excute query
1279
            pStmt.execute();
1280
            ResultSet rs = pStmt.getResultSet();
1281
            hasRow = rs.next();
1282
            // get result
1283
            if (hasRow) {
1284
                nodeId = rs.getLong(1);
1285
            }//if
1286

    
1287
        } catch (SQLException e) {
1288
            throw e;
1289
        } finally {
1290
            try {
1291
                pStmt.close();
1292
            } finally {
1293
                DBConnectionPool.returnDBConnection(conn, serialNumber);
1294
            }
1295
        }
1296
        logMetacat.debug("The nodeid for inlinedataid " + inLineDataId
1297
                + " is: " + nodeId);
1298
        return nodeId;
1299
    }
1300

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

    
1323
        try {
1324
            String[] docs = new String[0];
1325
            String docid = "";
1326
            String qformat = "";
1327
            String abstrpath = null;
1328

    
1329
            // read the params
1330
            if (params.containsKey("docid")) {
1331
                docs = (String[]) params.get("docid");
1332
            }
1333
            if (params.containsKey("qformat")) {
1334
                qformat = ((String[]) params.get("qformat"))[0];
1335
            }
1336
            // the param for only metadata (eml)
1337
            // we don't support read a eml document without inline data now.
1338
            /*if (params.containsKey("inlinedata")) {
1339

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

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

    
1371
                        // case docid="http://.../filename"
1372
                    } else {
1373
                        docid = docs[i];
1374
                        if (zip) {
1375
                            addDocToZip(request, docid, zout, user, groups);
1376
                        } else {
1377
                            readFromURLConnection(response, docid);
1378
                        }
1379
                    }
1380

    
1381
                } catch (MalformedURLException mue) {
1382
                    docid = docs[i];
1383
                    if (zip) {
1384
                        addDocToZip(request, docid, zout, user, groups);
1385
                    } else {
1386
                        readFromMetacat(request, response, docid, qformat,
1387
                                abstrpath, user, groups, zip, zout,
1388
                                withInlineData, params);
1389
                    }
1390
                }
1391
            }
1392

    
1393
            if (zip) {
1394
                zout.finish(); //terminate the zip file
1395
                zout.close(); //close the zip stream
1396
            }
1397

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

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

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

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

    
1481
                }
1482
                // Close zip output stream
1483
                if (zout != null) {
1484
                    zout.close();
1485
                }
1486

    
1487
            } catch (IOException ioe) {
1488
                logMetacat.error("Problem with the servlet output "
1489
                        + "in MetacatServlet.handleReadAction: "
1490
                        + ioe.getMessage());
1491
                ioe.printStackTrace(System.out);
1492

    
1493
            }
1494

    
1495
            logMetacat.error(
1496
                    "Error in MetacatServlet.handleReadAction: "
1497
                            + e.getMessage());
1498
            //e.printStackTrace(System.out);
1499
        }
1500
    }
1501

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

    
1524
            //check the permission for read
1525
            if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1526
                Exception e = new Exception("User " + user
1527
                        + " does not have permission"
1528
                        + " to read the document with the docid " + docid);
1529

    
1530
                throw e;
1531
            }
1532

    
1533
            if (doc.getRootNodeID() == 0) {
1534
                // this is data file
1535
                String filepath = MetaCatUtil.getOption("datafilepath");
1536
                if (!filepath.endsWith("/")) {
1537
                    filepath += "/";
1538
                }
1539
                String filename = filepath + docid;
1540
                FileInputStream fin = null;
1541
                fin = new FileInputStream(filename);
1542

    
1543
                //MIME type
1544
                String contentType = getServletContext().getMimeType(filename);
1545
                if (contentType == null) {
1546
                    ContentTypeProvider provider = new ContentTypeProvider(
1547
                            docid);
1548
                    contentType = provider.getContentType();
1549
                    logMetacat.info("Final contenttype is: "
1550
                            + contentType);
1551
                }
1552

    
1553
                response.setContentType(contentType);
1554
                // if we decide to use "application/octet-stream" for all data
1555
                // returns
1556
                // response.setContentType("application/octet-stream");
1557

    
1558
                try {
1559

    
1560
                    ServletOutputStream out = response.getOutputStream();
1561
                    byte[] buf = new byte[4 * 1024]; // 4K buffer
1562
                    int b = fin.read(buf);
1563
                    while (b != -1) {
1564
                        out.write(buf, 0, b);
1565
                        b = fin.read(buf);
1566
                    }
1567
                } finally {
1568
                    if (fin != null) fin.close();
1569
                }
1570

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

    
1584
                    // Look up the document type
1585
                    String doctype = doc.getDoctype();
1586
                    // Transform the document to the new doctype
1587
                    DBTransform dbt = new DBTransform();
1588
                    dbt.transformXMLDocument(doc.toString(user, groups,
1589
                            withInlineData), doctype, "-//W3C//HTML//EN",
1590
                            qformat, out, params);
1591
                }
1592

    
1593
            }
1594
            EventLog.getInstance().log(request.getRemoteAddr(), user,
1595
                    docid, "read");
1596
        } catch (Exception except) {
1597
            throw except;
1598
        }
1599
    }
1600

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

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

    
1649
    }
1650

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

    
1672
        try {
1673
            URL url = new URL(docid);
1674

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

    
1692
        } catch (MalformedURLException mue) {
1693

    
1694
            // this is metacat doc (data file or metadata doc)
1695
            try {
1696
                DocumentImpl doc = new DocumentImpl(docid);
1697

    
1698
                //check the permission for read
1699
                if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1700
                    Exception e = new Exception("User " + user
1701
                            + " does not have "
1702
                            + "permission to read the document with the docid "
1703
                            + docid);
1704
                    throw e;
1705
                }
1706

    
1707
                if (doc.getRootNodeID() == 0) {
1708
                    // this is data file; add file to zip
1709
                    String filepath = MetaCatUtil.getOption("datafilepath");
1710
                    if (!filepath.endsWith("/")) {
1711
                        filepath += "/";
1712
                    }
1713
                    String filename = filepath + docid;
1714
                    FileInputStream fin = null;
1715
                    fin = new FileInputStream(filename);
1716
                    try {
1717

    
1718
                        zentry = new ZipEntry(docid);
1719
                        zout.putNextEntry(zentry);
1720
                        byte[] buf = new byte[4 * 1024]; // 4K buffer
1721
                        int b = fin.read(buf);
1722
                        while (b != -1) {
1723
                            zout.write(buf, 0, b);
1724
                            b = fin.read(buf);
1725
                        }
1726
                    } finally {
1727
                        if (fin != null) fin.close();
1728
                    }
1729
                    zout.closeEntry();
1730

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

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

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

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

    
1809
        try {
1810
            // Get the document indicated
1811
            String[] doctext = (String[]) params.get("doctext");
1812
            String pub = null;
1813
            if (params.containsKey("public")) {
1814
                pub = ((String[]) params.get("public"))[0];
1815
            }
1816

    
1817
            StringReader dtd = null;
1818
            if (params.containsKey("dtdtext")) {
1819
                String[] dtdtext = (String[]) params.get("dtdtext");
1820
                try {
1821
                    if (!dtdtext[0].equals("")) {
1822
                        dtd = new StringReader(dtdtext[0]);
1823
                    }
1824
                } catch (NullPointerException npe) {
1825
                }
1826
            }
1827

    
1828
            if(doctext == null){
1829
                out.println("<?xml version=\"1.0\"?>");
1830
                out.println("<error>");
1831
                out.println("Document text not submitted");
1832
                out.println("</error>");
1833
                return;
1834
            }
1835

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

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

    
1878
                String[] action = (String[]) params.get("action");
1879
                String[] docid = (String[]) params.get("docid");
1880
                String newdocid = null;
1881

    
1882
                String doAction = null;
1883
                if (action[0].equals("insert")) {
1884
                    doAction = "INSERT";
1885
                } else if (action[0].equals("update")) {
1886
                    doAction = "UPDATE";
1887
                }
1888

    
1889
                try {
1890
                    // get a connection from the pool
1891
                    dbConn = DBConnectionPool
1892
                            .getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1893
                    serialNumber = dbConn.getCheckOutSerialNumber();
1894

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

    
1919
                // set content type and other response header fields first
1920
                //response.setContentType("text/xml");
1921
                out.println("<?xml version=\"1.0\"?>");
1922
                out.println("<success>");
1923
                out.println("<docid>" + newdocid + "</docid>");
1924
                out.println("</success>");
1925

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

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

    
1960
        // read from the stream until find the keywords
1961
        while ((st.empty() || st.size() < 4) && ((c = xmlreader.read()) != -1)) {
1962
            cbuff.append((char) c);
1963

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

    
1988
        // close the stream
1989
        xmlreader.reset();
1990

    
1991
        // check the stack whether it contains the keywords:
1992
        // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1993
        if (st.size() == 4) {
1994
            if (((String) st.pop()).equals(">")
1995
                    && (((String) st.peek()).equals("PUBLIC") | ((String) st
1996
                            .pop()).equals("SYSTEM"))
1997
                    && ((String) st.pop()).equals("<!DOCTYPE")) {
1998
                validate = true;
1999
            }
2000
        }
2001

    
2002
        logMetacat.info("Validation for dtd is " + validate);
2003
        return validate;
2004
    }
2005

    
2006
    // END OF INSERT/UPDATE SECTION
2007

    
2008
    /* check if the xml string contains key words to specify schema loocation */
2009
    private String findNamespace(StringReader xml) throws IOException
2010
    {
2011
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2012
        String namespace = null;
2013

    
2014
        String eml2_0_0NameSpace = DocumentImpl.EML2_0_0NAMESPACE;
2015
        String eml2_0_1NameSpace = DocumentImpl.EML2_0_1NAMESPACE;
2016
        String eml2_1_0NameSpace = DocumentImpl.EML2_1_0NAMESPACE;
2017

    
2018
        if (xml == null) {
2019
            logMetacat.debug("Validation for schema is "
2020
                    + namespace);
2021
            return namespace;
2022
        }
2023
        String targetLine = getSchemaLine(xml);
2024
		
2025
        if (targetLine != null) {
2026

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

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

    
2093
        logMetacat.debug("Validation for eml is " + namespace);
2094

    
2095
        return namespace;
2096

    
2097
    }
2098

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

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

    
2166
    private String getPrefix(String schemaLine)
2167
    {
2168
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2169
        String prefix = null;
2170
        
2171
        if(schemaLine.indexOf(" ") > 0){
2172
            String rootElement = "";
2173
            try {
2174
                rootElement = schemaLine.substring(0, schemaLine.indexOf(" "));
2175
            } catch (StringIndexOutOfBoundsException sioobe) {
2176
                rootElement = schemaLine;
2177
            }
2178

    
2179
            logMetacat.debug("rootElement:" + rootElement);
2180
        
2181
            if(rootElement.indexOf(":") > 0){
2182
                prefix = rootElement.substring(rootElement.indexOf(":") + 1,
2183
                    rootElement.length());
2184
            }
2185
            
2186
            if(prefix != null){
2187
                return prefix.trim();
2188
            }
2189
        }
2190
        return null;
2191
    }
2192

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

    
2204
        if(docid == null){
2205
          response.setContentType("text/xml");
2206
          out.println("<?xml version=\"1.0\"?>");
2207
          out.println("<error>");
2208
          out.println("Docid not specified.");
2209
          out.println("</error>");
2210
          logMetacat.error("Docid not specified for the document to be deleted.");
2211
        } else {
2212

    
2213
            // delete the document from the database
2214
            try {
2215

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

    
2228
                    // Delete from spatial cache
2229
                    SpatialHarvester sh = new SpatialHarvester();
2230
                    sh.addToDeleteQue( MetaCatUtil.getSmartDocId( docid[0] ) );
2231
                    sh.destroy();
2232

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

    
2257
    /**
2258
     * Handle the validation request and return the results to the requestor
2259
     */
2260
    private void handleValidateAction(PrintWriter out, Hashtable params)
2261
    {
2262

    
2263
        // Get the document indicated
2264
        String valtext = null;
2265
        DBConnection dbConn = null;
2266
        int serialNumber = -1;
2267

    
2268
        try {
2269
            valtext = ((String[]) params.get("valtext"))[0];
2270
        } catch (Exception nullpe) {
2271

    
2272
            String docid = null;
2273
            try {
2274
                // Find the document id number
2275
                docid = ((String[]) params.get("docid"))[0];
2276

    
2277
                // Get the document indicated from the db
2278
                DocumentImpl xmldoc = new DocumentImpl(docid);
2279
                valtext = xmldoc.toString();
2280

    
2281
            } catch (NullPointerException npe) {
2282

    
2283
                out.println("<error>Error getting document ID: " + docid
2284
                        + "</error>");
2285
                //if ( conn != null ) { util.returnConnection(conn); }
2286
                return;
2287
            } catch (Exception e) {
2288

    
2289
                out.println(e.getMessage());
2290
            }
2291
        }
2292

    
2293
        try {
2294
            // get a connection from the pool
2295
            dbConn = DBConnectionPool
2296
                    .getDBConnection("MetaCatServlet.handleValidateAction");
2297
            serialNumber = dbConn.getCheckOutSerialNumber();
2298
            DBValidate valobj = new DBValidate(dbConn);
2299
            boolean valid = valobj.validateString(valtext);
2300

    
2301
            // set content type and other response header fields first
2302

    
2303
            out.println(valobj.returnErrors());
2304

    
2305
        } catch (NullPointerException npe2) {
2306
            // set content type and other response header fields first
2307

    
2308
            out.println("<error>Error validating document.</error>");
2309
        } catch (Exception e) {
2310

    
2311
            out.println(e.getMessage());
2312
        } finally {
2313
            // Return db connection
2314
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2315
        }
2316
    }
2317

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

    
2337
        try {
2338
            // Make sure there is a docid
2339
            if (givenDocId == null || givenDocId.equals("")) { throw new Exception(
2340
                    "User didn't specify docid!"); }//if
2341

    
2342
            // Create a DBUtil object
2343
            DBUtil dbutil = new DBUtil();
2344
            // Get a rev and doctype
2345
            String revAndDocType = dbutil
2346
                    .getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
2347
            out.println(revAndDocType);
2348

    
2349
        } catch (Exception e) {
2350
            // Handle exception
2351
            out.println("<?xml version=\"1.0\"?>");
2352
            out.println("<error>");
2353
            out.println(e.getMessage());
2354
            out.println("</error>");
2355
        }
2356

    
2357
    }
2358

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

    
2371
        try {
2372

    
2373
            // get connection from the pool
2374
            dbConn = DBConnectionPool
2375
                    .getDBConnection("MetaCatServlet.handleGetAccessControlAction");
2376
            serialNumber = dbConn.getCheckOutSerialNumber();
2377
            AccessControlList aclobj = new AccessControlList(dbConn);
2378
            String acltext = aclobj.getACL(docid, username, groupnames);
2379
            out.println(acltext);
2380

    
2381
        } catch (Exception e) {
2382
            out.println("<?xml version=\"1.0\"?>");
2383
            out.println("<error>");
2384
            out.println(e.getMessage());
2385
            out.println("</error>");
2386
        } finally {
2387
            // Retrun db connection to pool
2388
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2389
        }
2390
    }
2391

    
2392
    /**
2393
     * Handle the "getprincipals" action. Read all principals from
2394
     * authentication scheme in XML format
2395
     */
2396
    private void handleGetPrincipalsAction(PrintWriter out, String user,
2397
            String password)
2398
    {
2399
        try {
2400
            AuthSession auth = new AuthSession();
2401
            String principals = auth.getPrincipals(user, password);
2402
            out.println(principals);
2403

    
2404
        } catch (Exception e) {
2405
            out.println("<?xml version=\"1.0\"?>");
2406
            out.println("<error>");
2407
            out.println(e.getMessage());
2408
            out.println("</error>");
2409
        }
2410
    }
2411

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

    
2431
    /**
2432
     * Handle the "getdtdschema" action. Read DTD or Schema file for a given
2433
     * doctype from Metacat catalog system
2434
     */
2435
    private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
2436
            HttpServletResponse response)
2437
    {
2438

    
2439
        String doctype = null;
2440
        String[] doctypeArr = (String[]) params.get("doctype");
2441

    
2442
        // get only the first doctype specified in the list of doctypes
2443
        // it could be done for all doctypes in that list
2444
        if (doctypeArr != null) {
2445
            doctype = ((String[]) params.get("doctype"))[0];
2446
        }
2447

    
2448
        try {
2449
            DBUtil dbutil = new DBUtil();
2450
            String dtdschema = dbutil.readDTDSchema(doctype);
2451
            out.println(dtdschema);
2452

    
2453
        } catch (Exception e) {
2454
            out.println("<?xml version=\"1.0\"?>");
2455
            out.println("<error>");
2456
            out.println(e.getMessage());
2457
            out.println("</error>");
2458
        }
2459

    
2460
    }
2461

    
2462
    /**
2463
     * Handle the "getlastdocid" action. Get the latest docid with rev number
2464
     * from db connection in XML format
2465
     */
2466
    private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
2467
            HttpServletResponse response)
2468
    {
2469

    
2470
        String scope = ((String[]) params.get("scope"))[0];
2471
        if (scope == null) {
2472
            scope = ((String[]) params.get("username"))[0];
2473
        }
2474

    
2475
        try {
2476

    
2477
            DBUtil dbutil = new DBUtil();
2478
            String lastDocid = dbutil.getMaxDocid(scope);
2479
            out.println("<?xml version=\"1.0\"?>");
2480
            out.println("<lastDocid>");
2481
            out.println("  <scope>" + scope + "</scope>");
2482
            out.println("  <docid>" + lastDocid + "</docid>");
2483
            out.println("</lastDocid>");
2484

    
2485
        } catch (Exception e) {
2486
            out.println("<?xml version=\"1.0\"?>");
2487
            out.println("<error>");
2488
            out.println(e.getMessage());
2489
            out.println("</error>");
2490
        }
2491
    }
2492

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

    
2509
            // Check that the user is authenticated as an administrator account
2510
            if (!MetaCatUtil.isAdministrator(username, groups)) {
2511
                out.print("<error>");
2512
                out.print("The user \"" + username +
2513
                        "\" is not authorized for this action.");
2514
                out.print("</error>");
2515
                return;
2516
            }
2517

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

    
2547
            // Request the report by passing the filter parameters
2548
            out.println(EventLog.getInstance().getReport(ipAddress, principal,
2549
                    docid, event, startDate, endDate));
2550
            out.close();
2551
        } catch (IOException e) {
2552
            logMetacat.error(
2553
                    "Could not open http response for writing: " + e.getMessage());
2554
        }
2555
    }
2556

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

    
2577
        // Rebuild the indices for appropriate documents
2578
        try {
2579
            response.setContentType("text/xml");
2580
            PrintWriter out = response.getWriter();
2581

    
2582
            // Check that the user is authenticated as an administrator account
2583
            if (!MetaCatUtil.isAdministrator(username, groups)) {
2584
                out.print("<error>");
2585
                out.print("The user \"" + username +
2586
                        "\" is not authorized for this action.");
2587
                out.print("</error>");
2588
                return;
2589
            }
2590

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

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

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

    
2655
        // Parse the multipart form, and save the parameters in a Hashtable and
2656
        // save the FileParts in a hashtable
2657

    
2658
        Hashtable params = new Hashtable();
2659
        Hashtable fileList = new Hashtable();
2660
        int sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit")))
2661
                .intValue();
2662
        logMetacat.info(
2663
                "The size limit of uploaded data files is: " + sizeLimit);
2664

    
2665
        try {
2666
            MultipartParser mp = new MultipartParser(request,
2667
                    sizeLimit * 1024 * 1024);
2668
            Part part;
2669
            while ((part = mp.readNextPart()) != null) {
2670
                String name = part.getName();
2671

    
2672
                if (part.isParam()) {
2673
                    // it's a parameter part
2674
                    ParamPart paramPart = (ParamPart) part;
2675
                    String value = paramPart.getStringValue();
2676
                    params.put(name, value);
2677
                    if (name.equals("action")) {
2678
                        action = value;
2679
                    }
2680
                } else if (part.isFile()) {
2681
                    // it's a file part
2682
                    FilePart filePart = (FilePart) part;
2683
                    fileList.put(name, filePart);
2684

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

    
2705
        // Get the session information
2706
        String username = null;
2707
        String password = null;
2708
        String[] groupnames = null;
2709
        String sess_id = null;
2710

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

    
2731
        // Get the out stream
2732
        try {
2733
            out = response.getWriter();
2734
        } catch (IOException ioe2) {
2735
            logMetacat.error("Fatal Error: couldn't get response "
2736
                    + "output stream.");
2737
        }
2738

    
2739
        if (action.equals("upload")) {
2740
            if (username != null && !username.equals("public")) {
2741
                handleUploadAction(request, out, params, fileList, username,
2742
                        groupnames);
2743
            } else {
2744

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

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

    
2779
        /*
2780
         * response.setContentType("text/xml"); try { out =
2781
         * response.getWriter(); } catch (IOException ioe2) {
2782
         * System.err.println("Fatal Error: couldn't get response output
2783
         * stream.");
2784
         */
2785

    
2786
        if (params.containsKey("docid")) {
2787
            docid = (String) params.get("docid");
2788
        }
2789

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

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

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

    
2842
                        // set content type and other response header fields
2843
                        // first
2844
                        out.println("<?xml version=\"1.0\"?>");
2845
                        out.println("<success>");
2846
                        out.println("<docid>" + docid + "</docid>");
2847
                        out.println("<size>" + size + "</size>");
2848
                        out.println("</success>");
2849
                    }
2850

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

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

    
2895
        // Get parameters
2896
        if (params.containsKey("docid")) {
2897
            docList = (String[]) params.get("docid");
2898
        }
2899
        if (params.containsKey("principal")) {
2900
            principalList = (String[]) params.get("principal");
2901
        }
2902
        if (params.containsKey("permission")) {
2903
            permissionList = (String[]) params.get("permission");
2904

    
2905
        }
2906
        if (params.containsKey("permType")) {
2907
            permTypeList = (String[]) params.get("permType");
2908

    
2909
        }
2910
        if (params.containsKey("permOrder")) {
2911
            permOrderList = (String[]) params.get("permOrder");
2912

    
2913
        }
2914

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

    
2926
        // Only select first element for permission, type and order
2927
        permission = permissionList[0];
2928
        permType = permTypeList[0];
2929
        if (permOrderList != null) {
2930
            permOrder = permOrderList[0];
2931
        }
2932

    
2933
        // Get package doctype set
2934
        Vector packageSet = MetaCatUtil.getOptionList(MetaCatUtil
2935
                .getOption("packagedoctypeset"));
2936
        //debug
2937
        if (packageSet != null) {
2938
            for (int i = 0; i < packageSet.size(); i++) {
2939
                logMetacat.debug("doctype in package set: "
2940
                        + (String) packageSet.elementAt(i));
2941
            }
2942
        }
2943

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

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

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

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

    
3022
        PreparedStatement pstmt = null;
3023
        ResultSet rs = null;
3024
        String fieldValue = null;
3025
        String docId = null;
3026
        DBConnection conn = null;
3027
        int serialNumber = -1;
3028

    
3029
        // get rid of revision if access number has
3030
        docId = MetaCatUtil.getDocIdFromString(accessionNumber);
3031
        try {
3032
            //check out DBConnection
3033
            conn = DBConnectionPool
3034
                    .getDBConnection("MetaCatServlet.getPublicIdForDoc");
3035
            serialNumber = conn.getCheckOutSerialNumber();
3036
            pstmt = conn.prepareStatement("SELECT " + fieldName
3037
                    + " FROM xml_documents " + "WHERE docid = ? ");
3038

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

    
3060
            } finally {
3061
                DBConnectionPool.returnDBConnection(conn, serialNumber);
3062
            }
3063
        }
3064
        return fieldValue;
3065
    }
3066

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

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

    
3106
            } catch (SQLException se) {
3107
                logMetacat.error(
3108
                    "Exception in MetacatServlet.getDocumentList: "
3109
                            + se.getMessage());
3110
                throw se;
3111
            } finally {
3112
                DBConnectionPool.returnDBConnection(conn, serialNumber);
3113
            }
3114
        }
3115
        return docList;
3116
    }
3117

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

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