Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements a metadata catalog as a java Servlet
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Matt Jones, Dan Higgins, Jivka Bojilova, Chad Berkley, Matthew Perry
7
 *    Release: @release@
8
 *
9
 *   '$Author: perry $'
10
 *     '$Date: 2006-09-13 16:10:55 -0700 (Wed, 13 Sep 2006) $'
11
 * '$Revision: 3044 $'
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

    
808
        SpatialQuery sq = new SpatialQuery();
809
        Vector docids = sq.filterByBbox( _xmin, _ymin, _xmax, _ymax );
810
        logMetacat.info(" --- Spatial Query completed. Passing on the SQuery handler");
811

    
812
        /*
813
         * Create an squery based on vector of matching docids
814
         */
815
        String [] docidArray = new String[docids.size()];
816
        docids.toArray(docidArray);
817
        String squery = DocumentIdQuery.createDocidQuery( docidArray );
818

    
819
        /*
820
         * Pass to squery handler
821
         */
822
        String[] queryArray = new String[1];
823
        queryArray[0] = squery;
824
        params.put("query", queryArray);
825

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

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

    
843
        handleSQuery(out, params, response, username, groupnames, sess_id);
844

    
845
  }
846

    
847
    /**
848
     * Create a metacat squery for spatial data coordinates.
849
     */
850
    private String createSpatialQuery(float _xmin, float _ymin, float _xmax, float _ymax) {
851
	StringBuffer sb = new StringBuffer();
852
	    
853
	sb.append("<pathquery version=\"1.2\">");
854
	sb.append("<querytitle>Untitled-Search-3</querytitle>");
855
	sb.append("<returndoctype>-//ecoinformatics.org//eml-dataset-2.0.0beta4//EN</returndoctype>");
856
	sb.append("<returndoctype>-//ecoinformatics.org//eml-dataset-2.0.0beta6//EN</returndoctype>");
857
	sb.append("<returndoctype>-//NCEAS//eml-dataset-2.0//EN</returndoctype>");
858
	sb.append("<returndoctype>-//NCEAS//resource//EN</returndoctype>");
859
	sb.append("<returndoctype>eml://ecoinformatics.org/eml-2.0.0</returndoctype>");
860
	sb.append("<returndoctype>eml://ecoinformatics.org/eml-2.0.1</returndoctype>");
861
	sb.append("<returndoctype>metadata</returndoctype>");
862
	sb.append("<returnfield>dataset/title</returnfield>");
863
	sb.append("<returnfield>originator/individualName/surName</returnfield>");
864
	sb.append("<returnfield>originator/individualName/givenName</returnfield>");
865
	sb.append("<returnfield>originator/organizationName</returnfield>");
866
	sb.append("<returnfield>creator/individualName/surName</returnfield>");
867
	sb.append("<returnfield>creator/individualName/givenName</returnfield>");
868
	sb.append("<returnfield>creator/organizationName</returnfield>");
869
	sb.append("<returnfield>keyword</returnfield>");
870
	sb.append("<returnfield>entityName</returnfield>");
871
	sb.append("<returnfield>idinfo/citation/citeinfo/title</returnfield>");
872
	sb.append("<returnfield>idinfo/citation/citeinfo/origin</returnfield>");
873
	sb.append("<returnfield>idinfo/keywords/theme/themekey</returnfield>");
874
	sb.append("<querygroup operator=\"INTERSECT\">");
875
	sb.append("<queryterm searchmode=\"greater-than\" casesensitive=\"false\">");
876
	sb.append("<value>" + _ymin + "</value>");
877
	sb.append("<pathexpr>northBoundingCoordinate</pathexpr>");
878
	sb.append("</queryterm>");
879
	sb.append("<queryterm searchmode=\"less-than\" casesensitive=\"false\">");
880
	sb.append("<value>" + _ymax + "</value>");
881
	sb.append("<pathexpr>southBoundingCoordinate</pathexpr>");
882
	sb.append("</queryterm>");
883
	sb.append("<queryterm searchmode=\"greater-than\" casesensitive=\"false\">");
884
	sb.append("<value>" + _xmin + "</value>");
885
	sb.append("<pathexpr>eastBoundingCoordinate</pathexpr>");
886
	sb.append("</queryterm>");
887
 	sb.append("<queryterm searchmode=\"less-than\" casesensitive=\"false\">");
888
	sb.append("<value>" + _xmax + "</value>");
889
	sb.append("<pathexpr>westBoundingCoordinate</pathexpr>");
890
	sb.append("</queryterm>");
891
	sb.append("</querygroup>");
892
	sb.append("</pathquery>");
893

    
894
	return sb.toString();
895
    }
896

    
897
    // LOGIN & LOGOUT SECTION
898
    /**
899
     * Handle the login request. Create a new session object. Do user
900
     * authentication through the session.
901
     */
902
    private void handleLoginAction(PrintWriter out, Hashtable params,
903
            HttpServletRequest request, HttpServletResponse response)
904
    {
905
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
906
        AuthSession sess = null;
907

    
908
        if(params.get("username") == null){
909
            response.setContentType("text/xml");
910
            out.println("<?xml version=\"1.0\"?>");
911
            out.println("<error>");
912
            out.println("Username not specified");
913
            out.println("</error>");
914
            return;
915
        }
916

    
917
        //}
918

    
919
        if(params.get("password") == null){
920
            response.setContentType("text/xml");
921
            out.println("<?xml version=\"1.0\"?>");
922
            out.println("<error>");
923
            out.println("Password not specified");
924
            out.println("</error>");
925
            return;
926
        }
927

    
928
        String un = ((String[]) params.get("username"))[0];
929
        logMetacat.info("user " + un + " is trying to login");
930
        String pw = ((String[]) params.get("password"))[0];
931

    
932
        String qformat = "xml";
933
        if(params.get("qformat") != null){
934
            qformat = ((String[]) params.get("qformat"))[0];
935
        }
936

    
937
        try {
938
            sess = new AuthSession();
939
        } catch (Exception e) {
940
            System.out.println("error in MetacatServlet.handleLoginAction: "
941
                    + e.getMessage());
942
            out.println(e.getMessage());
943
            return;
944
        }
945
        boolean isValid = sess.authenticate(request, un, pw);
946

    
947
        //if it is authernticate is true, store the session
948
        if (isValid) {
949
            HttpSession session = sess.getSessions();
950
            String id = session.getId();
951
            logMetacat.info("Store session id " + id
952
                    + "which has username" + session.getAttribute("username")
953
                    + " into hash in login method");
954
            sessionHash.put(id, session);
955
        }
956

    
957
        // format and transform the output
958
        if (qformat.equals("xml")) {
959
            response.setContentType("text/xml");
960
            out.println(sess.getMessage());
961
        } else {
962
            try {
963
                DBTransform trans = new DBTransform();
964
                response.setContentType("text/html");
965
                trans.transformXMLDocument(sess.getMessage(),
966
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
967
                        out, null);
968
            } catch (Exception e) {
969

    
970
                logMetacat.error(
971
                        "Error in MetaCatServlet.handleLoginAction: "
972
                                + e.getMessage());
973
            }
974
        }
975
    }
976

    
977
    /**
978
     * Handle the logout request. Close the connection.
979
     */
980
    private void handleLogoutAction(PrintWriter out, Hashtable params,
981
            HttpServletRequest request, HttpServletResponse response)
982
    {
983
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
984
        String qformat = "xml";
985
        if(params.get("qformat") != null){
986
            qformat = ((String[]) params.get("qformat"))[0];
987
        }
988

    
989
        // close the connection
990
        HttpSession sess = request.getSession(false);
991
        logMetacat.info("After get session in logout request");
992
        if (sess != null) {
993
            logMetacat.info("The session id " + sess.getId()
994
                    + " will be invalidate in logout action");
995
            logMetacat.info("The session contains user "
996
                    + sess.getAttribute("username")
997
                    + " will be invalidate in logout action");
998
            sess.invalidate();
999
        }
1000

    
1001
        // produce output
1002
        StringBuffer output = new StringBuffer();
1003
        output.append("<?xml version=\"1.0\"?>");
1004
        output.append("<logout>");
1005
        output.append("User logged out");
1006
        output.append("</logout>");
1007

    
1008
        //format and transform the output
1009
        if (qformat.equals("xml")) {
1010
            response.setContentType("text/xml");
1011
            out.println(output.toString());
1012
        } else {
1013
            try {
1014
                DBTransform trans = new DBTransform();
1015
                response.setContentType("text/html");
1016
                trans.transformXMLDocument(output.toString(),
1017
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
1018
                        out, null);
1019
            } catch (Exception e) {
1020
                logMetacat.error(
1021
                        "Error in MetaCatServlet.handleLogoutAction"
1022
                                + e.getMessage());
1023
            }
1024
        }
1025
    }
1026

    
1027
    // END OF LOGIN & LOGOUT SECTION
1028

    
1029
    // SQUERY & QUERY SECTION
1030
    /**
1031
     * Retreive the squery xml, execute it and display it
1032
     *
1033
     * @param out the output stream to the client
1034
     * @param params the Hashtable of parameters that should be included in the
1035
     *            squery.
1036
     * @param response the response object linked to the client
1037
     * @param conn the database connection
1038
     */
1039
    private void handleSQuery(PrintWriter out, Hashtable params,
1040
            HttpServletResponse response, String user, String[] groups,
1041
            String sessionid)
1042
    {
1043
        double startTime = System.currentTimeMillis() / 1000;
1044
        DBQuery queryobj = new DBQuery();
1045
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
1046
        double outPutTime = System.currentTimeMillis() / 1000;
1047
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1048
        logMetacat.info("Total search time for action 'squery': "
1049
                + (outPutTime - startTime));
1050
    }
1051

    
1052
    /**
1053
     * Create the xml query, execute it and display the results.
1054
     *
1055
     * @param out the output stream to the client
1056
     * @param params the Hashtable of parameters that should be included in the
1057
     *            squery.
1058
     * @param response the response object linked to the client
1059
     */
1060
    private void handleQuery(PrintWriter out, Hashtable params,
1061
            HttpServletResponse response, String user, String[] groups,
1062
            String sessionid)
1063
    {
1064
        //create the query and run it
1065
        String xmlquery = DBQuery.createSQuery(params);
1066
        String[] queryArray = new String[1];
1067
        queryArray[0] = xmlquery;
1068
        params.put("query", queryArray);
1069
        double startTime = System.currentTimeMillis() / 1000;
1070
        DBQuery queryobj = new DBQuery();
1071
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
1072
        double outPutTime = System.currentTimeMillis() / 1000;
1073
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1074
        logMetacat.info("Total search time for action 'query': "
1075
                + (outPutTime - startTime));
1076

    
1077
        //handleSQuery(out, params, response,user, groups, sessionid);
1078
    }
1079

    
1080
    // END OF SQUERY & QUERY SECTION
1081

    
1082
    //Exoport section
1083
    /**
1084
     * Handle the "export" request of data package from Metacat in zip format
1085
     *
1086
     * @param params the Hashtable of HTTP request parameters
1087
     * @param response the HTTP response object linked to the client
1088
     * @param user the username sent the request
1089
     * @param groups the user's groupnames
1090
     */
1091
    private void handleExportAction(Hashtable params,
1092
            HttpServletResponse response,
1093
            String user, String[] groups, String passWord)
1094
    {
1095
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1096
        // Output stream
1097
        ServletOutputStream out = null;
1098
        // Zip output stream
1099
        ZipOutputStream zOut = null;
1100
        DBQuery queryObj = null;
1101

    
1102
        String[] docs = new String[10];
1103
        String docId = "";
1104

    
1105
        try {
1106
            // read the params
1107
            if (params.containsKey("docid")) {
1108
                docs = (String[]) params.get("docid");
1109
            }
1110
            // Create a DBuery to handle export
1111
            queryObj = new DBQuery();
1112
            // Get the docid
1113
            docId = docs[0];
1114
            // Make sure the client specify docid
1115
            if (docId == null || docId.equals("")) {
1116
                response.setContentType("text/xml"); //MIME type
1117
                // Get a printwriter
1118
                PrintWriter pw = response.getWriter();
1119
                // Send back message
1120
                pw.println("<?xml version=\"1.0\"?>");
1121
                pw.println("<error>");
1122
                pw.println("You didn't specify requested docid");
1123
                pw.println("</error>");
1124
                // Close printwriter
1125
                pw.close();
1126
                return;
1127
            }
1128
            // Get output stream
1129
            out = response.getOutputStream();
1130
            response.setContentType("application/zip"); //MIME type
1131
            response.setHeader("Content-Disposition", 
1132
            		"attachment; filename=" 
1133
            		+ docId + ".zip"); // Set the name of the zip file
1134
            		
1135
            zOut = new ZipOutputStream(out);
1136
            zOut = queryObj
1137
                    .getZippedPackage(docId, out, user, groups, passWord);
1138
            zOut.finish(); //terminate the zip file
1139
            zOut.close(); //close the zip stream
1140

    
1141
        } catch (Exception e) {
1142
            try {
1143
                response.setContentType("text/xml"); //MIME type
1144
                // Send error message back
1145
                if (out != null) {
1146
                    PrintWriter pw = new PrintWriter(out);
1147
                    pw.println("<?xml version=\"1.0\"?>");
1148
                    pw.println("<error>");
1149
                    pw.println(e.getMessage());
1150
                    pw.println("</error>");
1151
                    // Close printwriter
1152
                    pw.close();
1153
                    // Close output stream
1154
                    out.close();
1155
                }
1156
                // Close zip output stream
1157
                if (zOut != null) {
1158
                    zOut.close();
1159
                }
1160
            } catch (IOException ioe) {
1161
                logMetacat.error("Problem with the servlet output "
1162
                        + "in MetacatServlet.handleExportAction: "
1163
                        + ioe.getMessage());
1164
            }
1165

    
1166
            logMetacat.error(
1167
                    "Error in MetacatServlet.handleExportAction: "
1168
                            + e.getMessage());
1169
            e.printStackTrace(System.out);
1170

    
1171
        }
1172

    
1173
    }
1174

    
1175
    /**
1176
     * In eml2 document, the xml can have inline data and data was stripped off
1177
     * and store in file system. This action can be used to read inline data
1178
     * only
1179
     *
1180
     * @param params the Hashtable of HTTP request parameters
1181
     * @param response the HTTP response object linked to the client
1182
     * @param user the username sent the request
1183
     * @param groups the user's groupnames
1184
     */
1185
    private void handleReadInlineDataAction(Hashtable params,
1186
            HttpServletRequest request, HttpServletResponse response,
1187
            String user, String passWord, String[] groups)
1188
    {
1189
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1190
        String[] docs = new String[10];
1191
        String inlineDataId = null;
1192
        String docId = "";
1193
        ServletOutputStream out = null;
1194

    
1195
        try {
1196
            // read the params
1197
            if (params.containsKey("inlinedataid")) {
1198
                docs = (String[]) params.get("inlinedataid");
1199
            }
1200
            // Get the docid
1201
            inlineDataId = docs[0];
1202
            // Make sure the client specify docid
1203
            if (inlineDataId == null || inlineDataId.equals("")) {
1204
                throw new Exception("You didn't specify requested inlinedataid"); }
1205

    
1206
            // check for permission
1207
            docId = MetaCatUtil
1208
                    .getDocIdWithoutRevFromInlineDataID(inlineDataId);
1209
            PermissionController controller = new PermissionController(docId);
1210
            // check top level read permission
1211
            if (!controller.hasPermission(user, groups,
1212
                    AccessControlInterface.READSTRING))
1213
            {
1214
                throw new Exception("User " + user
1215
                        + " doesn't have permission " + " to read document "
1216
                        + docId);
1217
            }
1218
            else
1219
            {
1220
              //check data access level
1221
              try
1222
              {
1223
                Hashtable unReadableInlineDataList =
1224
                    PermissionController.getUnReadableInlineDataIdList(docId,
1225
                    user, groups, false);
1226
                if (unReadableInlineDataList.containsValue(
1227
                          MetaCatUtil.getInlineDataIdWithoutRev(inlineDataId)))
1228
                {
1229
                  throw new Exception("User " + user
1230
                       + " doesn't have permission " + " to read inlinedata "
1231
                       + inlineDataId);
1232

    
1233
                }//if
1234
              }//try
1235
              catch (Exception e)
1236
              {
1237
                throw e;
1238
              }//catch
1239
            }//else
1240

    
1241
            // Get output stream
1242
            out = response.getOutputStream();
1243
            // read the inline data from the file
1244
            String inlinePath = MetaCatUtil.getOption("inlinedatafilepath");
1245
            File lineData = new File(inlinePath, inlineDataId);
1246
            FileInputStream input = new FileInputStream(lineData);
1247
            byte[] buffer = new byte[4 * 1024];
1248
            int bytes = input.read(buffer);
1249
            while (bytes != -1) {
1250
                out.write(buffer, 0, bytes);
1251
                bytes = input.read(buffer);
1252
            }
1253
            out.close();
1254

    
1255
            EventLog.getInstance().log(request.getRemoteAddr(), user,
1256
                    inlineDataId, "readinlinedata");
1257
        } catch (Exception e) {
1258
            try {
1259
                PrintWriter pw = null;
1260
                // Send error message back
1261
                if (out != null) {
1262
                    pw = new PrintWriter(out);
1263
                } else {
1264
                    pw = response.getWriter();
1265
                }
1266
                pw.println("<?xml version=\"1.0\"?>");
1267
                pw.println("<error>");
1268
                pw.println(e.getMessage());
1269
                pw.println("</error>");
1270
                // Close printwriter
1271
                pw.close();
1272
                // Close output stream if out is not null
1273
                if (out != null) {
1274
                    out.close();
1275
                }
1276
            } catch (IOException ioe) {
1277
                logMetacat.error("Problem with the servlet output "
1278
                        + "in MetacatServlet.handleExportAction: "
1279
                        + ioe.getMessage());
1280
            }
1281
            logMetacat.error(
1282
                    "Error in MetacatServlet.handleReadInlineDataAction: "
1283
                            + e.getMessage());
1284
        }
1285
    }
1286

    
1287
    /*
1288
     * Get the nodeid from xml_nodes for the inlinedataid
1289
     */
1290
    private long getInlineDataNodeId(String inLineDataId, String docId)
1291
            throws SQLException
1292
    {
1293
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1294
        long nodeId = 0;
1295
        String INLINE = "inline";
1296
        boolean hasRow;
1297
        PreparedStatement pStmt = null;
1298
        DBConnection conn = null;
1299
        int serialNumber = -1;
1300
        String sql = "SELECT nodeid FROM xml_nodes WHERE docid=? AND nodedata=? "
1301
                + "AND nodetype='TEXT' AND parentnodeid IN "
1302
                + "(SELECT nodeid FROM xml_nodes WHERE docid=? AND "
1303
                + "nodetype='ELEMENT' AND nodename='" + INLINE + "')";
1304

    
1305
        try {
1306
            //check out DBConnection
1307
            conn = DBConnectionPool
1308
                    .getDBConnection("AccessControlList.isAllowFirst");
1309
            serialNumber = conn.getCheckOutSerialNumber();
1310

    
1311
            pStmt = conn.prepareStatement(sql);
1312
            //bind value
1313
            pStmt.setString(1, docId);//docid
1314
            pStmt.setString(2, inLineDataId);//inlinedataid
1315
            pStmt.setString(3, docId);
1316
            // excute query
1317
            pStmt.execute();
1318
            ResultSet rs = pStmt.getResultSet();
1319
            hasRow = rs.next();
1320
            // get result
1321
            if (hasRow) {
1322
                nodeId = rs.getLong(1);
1323
            }//if
1324

    
1325
        } catch (SQLException e) {
1326
            throw e;
1327
        } finally {
1328
            try {
1329
                pStmt.close();
1330
            } finally {
1331
                DBConnectionPool.returnDBConnection(conn, serialNumber);
1332
            }
1333
        }
1334
        logMetacat.debug("The nodeid for inlinedataid " + inLineDataId
1335
                + " is: " + nodeId);
1336
        return nodeId;
1337
    }
1338

    
1339
    /**
1340
     * Handle the "read" request of metadata/data files from Metacat or any
1341
     * files from Internet; transformed metadata XML document into HTML
1342
     * presentation if requested; zip files when more than one were requested.
1343
     *
1344
     * @param params the Hashtable of HTTP request parameters
1345
     * @param request the HTTP request object linked to the client
1346
     * @param response the HTTP response object linked to the client
1347
     * @param user the username sent the request
1348
     * @param groups the user's groupnames
1349
     */
1350
    private void handleReadAction(Hashtable params, HttpServletRequest request,
1351
            HttpServletResponse response, String user, String passWord,
1352
            String[] groups)
1353
    {
1354
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1355
        ServletOutputStream out = null;
1356
        ZipOutputStream zout = null;
1357
        PrintWriter pw = null;
1358
        boolean zip = false;
1359
        boolean withInlineData = true;
1360

    
1361
        try {
1362
            String[] docs = new String[0];
1363
            String docid = "";
1364
            String qformat = "";
1365
            String abstrpath = null;
1366

    
1367
            // read the params
1368
            if (params.containsKey("docid")) {
1369
                docs = (String[]) params.get("docid");
1370
            }
1371
            if (params.containsKey("qformat")) {
1372
                qformat = ((String[]) params.get("qformat"))[0];
1373
            }
1374
            // the param for only metadata (eml)
1375
            // we don't support read a eml document without inline data now.
1376
            /*if (params.containsKey("inlinedata")) {
1377

    
1378
                String inlineData = ((String[]) params.get("inlinedata"))[0];
1379
                if (inlineData.equalsIgnoreCase("false")) {
1380
                    withInlineData = false;
1381
                }
1382
            }*/
1383
            if ((docs.length > 1) || qformat.equals("zip")) {
1384
                zip = true;
1385
                out = response.getOutputStream();
1386
                response.setContentType("application/zip"); //MIME type
1387
                zout = new ZipOutputStream(out);
1388
            }
1389
            // go through the list of docs to read
1390
            for (int i = 0; i < docs.length; i++) {
1391
                try {
1392

    
1393
                    URL murl = new URL(docs[i]);
1394
                    Hashtable murlQueryStr = MetaCatUtil.parseQuery(
1395
                            murl.getQuery());
1396
                    // case docid="http://.../?docid=aaa"
1397
                    // or docid="metacat://.../?docid=bbb"
1398
                    if (murlQueryStr.containsKey("docid")) {
1399
                        // get only docid, eliminate the rest
1400
                        docid = (String) murlQueryStr.get("docid");
1401
                        if (zip) {
1402
                            addDocToZip(request, docid, zout, user, groups);
1403
                        } else {
1404
                            readFromMetacat(request, response, docid, qformat,
1405
                                    abstrpath, user, groups, zip, zout,
1406
                                    withInlineData, params);
1407
                        }
1408

    
1409
                        // case docid="http://.../filename"
1410
                    } else {
1411
                        docid = docs[i];
1412
                        if (zip) {
1413
                            addDocToZip(request, docid, zout, user, groups);
1414
                        } else {
1415
                            readFromURLConnection(response, docid);
1416
                        }
1417
                    }
1418

    
1419
                } catch (MalformedURLException mue) {
1420
                    docid = docs[i];
1421
                    if (zip) {
1422
                        addDocToZip(request, docid, zout, user, groups);
1423
                    } else {
1424
                        readFromMetacat(request, response, docid, qformat,
1425
                                abstrpath, user, groups, zip, zout,
1426
                                withInlineData, params);
1427
                    }
1428
                }
1429
            }
1430

    
1431
            if (zip) {
1432
                zout.finish(); //terminate the zip file
1433
                zout.close(); //close the zip stream
1434
            }
1435

    
1436
        } catch (McdbDocNotFoundException notFoundE) {
1437
            // To handle doc not found exception
1438
            // the docid which didn't be found
1439
            String notFoundDocId = notFoundE.getUnfoundDocId();
1440
            String notFoundRevision = notFoundE.getUnfoundRevision();
1441
            logMetacat.warn("Missed id: " + notFoundDocId);
1442
            logMetacat.warn("Missed rev: " + notFoundRevision);
1443
            try {
1444
                // read docid from remote server
1445
                readFromRemoteMetaCat(response, notFoundDocId,
1446
                        notFoundRevision, user, passWord, out, zip, zout);
1447
                // Close zout outputstream
1448
                if (zout != null) {
1449
                    zout.close();
1450
                }
1451
                // close output stream
1452
                if (out != null) {
1453
                    out.close();
1454
                }
1455

    
1456
            } catch (Exception exc) {
1457
                logMetacat.error(
1458
                        "Erorr in MetacatServlet.hanldReadAction: "
1459
                                + exc.getMessage());
1460
                try {
1461
                    if (out != null) {
1462
                        response.setContentType("text/xml");
1463
                        // Send back error message by printWriter
1464
                        pw = new PrintWriter(out);
1465
                        pw.println("<?xml version=\"1.0\"?>");
1466
                        pw.println("<error>");
1467
                        pw.println(notFoundE.getMessage());
1468
                        pw.println("</error>");
1469
                        pw.close();
1470
                        out.close();
1471

    
1472
                    } else {
1473
                        response.setContentType("text/xml"); //MIME type
1474
                        // Send back error message if out = null
1475
                        if (pw == null) {
1476
                            // If pw is null, open the respnose
1477
                            pw = response.getWriter();
1478
                        }
1479
                        pw.println("<?xml version=\"1.0\"?>");
1480
                        pw.println("<error>");
1481
                        pw.println(notFoundE.getMessage());
1482
                        pw.println("</error>");
1483
                        pw.close();
1484
                    }
1485
                    // close zout
1486
                    if (zout != null) {
1487
                        zout.close();
1488
                    }
1489
                } catch (IOException ie) {
1490
                    logMetacat.error("Problem with the servlet output "
1491
                            + "in MetacatServlet.handleReadAction: "
1492
                            + ie.getMessage());
1493
                }
1494
            }
1495
        } catch (Exception e) {
1496
            try {
1497

    
1498
                if (out != null) {
1499
                    response.setContentType("text/xml"); //MIME type
1500
                    pw = new PrintWriter(out);
1501
                    pw.println("<?xml version=\"1.0\"?>");
1502
                    pw.println("<error>");
1503
                    pw.println(e.getMessage());
1504
                    pw.println("</error>");
1505
                    pw.close();
1506
                    out.close();
1507
                } else {
1508
                    response.setContentType("text/xml"); //MIME type
1509
                    // Send back error message if out = null
1510
                    if (pw == null) {
1511
                        pw = response.getWriter();
1512
                    }
1513
                    pw.println("<?xml version=\"1.0\"?>");
1514
                    pw.println("<error>");
1515
                    pw.println(e.getMessage());
1516
                    pw.println("</error>");
1517
                    pw.close();
1518

    
1519
                }
1520
                // Close zip output stream
1521
                if (zout != null) {
1522
                    zout.close();
1523
                }
1524

    
1525
            } catch (IOException ioe) {
1526
                logMetacat.error("Problem with the servlet output "
1527
                        + "in MetacatServlet.handleReadAction: "
1528
                        + ioe.getMessage());
1529
                ioe.printStackTrace(System.out);
1530

    
1531
            }
1532

    
1533
            logMetacat.error(
1534
                    "Error in MetacatServlet.handleReadAction: "
1535
                            + e.getMessage());
1536
            //e.printStackTrace(System.out);
1537
        }
1538
    }
1539

    
1540
    /** read metadata or data from Metacat
1541
     */
1542
    private void readFromMetacat(HttpServletRequest request,
1543
            HttpServletResponse response, String docid, String qformat,
1544
            String abstrpath, String user, String[] groups, boolean zip,
1545
            ZipOutputStream zout, boolean withInlineData, Hashtable params)
1546
            throws ClassNotFoundException, IOException, SQLException,
1547
            McdbException, Exception
1548
    {
1549
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1550
        try {
1551
            
1552
            // here is hack for handle docid=john.10(in order to tell mike.jim.10.1
1553
            // mike.jim.10, we require to provide entire docid with rev). But
1554
            // some old client they only provide docid without rev, so we need
1555
            // to handle this suituation. First we will check how many
1556
            // seperator here, if only one, we will append the rev in xml_documents
1557
            // to the id.
1558
            docid = appendRev(docid);
1559
         
1560
            DocumentImpl doc = new DocumentImpl(docid);
1561

    
1562
            //check the permission for read
1563
            if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1564
                Exception e = new Exception("User " + user
1565
                        + " does not have permission"
1566
                        + " to read the document with the docid " + docid);
1567

    
1568
                throw e;
1569
            }
1570

    
1571
            if (doc.getRootNodeID() == 0) {
1572
                // this is data file
1573
                String filepath = MetaCatUtil.getOption("datafilepath");
1574
                if (!filepath.endsWith("/")) {
1575
                    filepath += "/";
1576
                }
1577
                String filename = filepath + docid;
1578
                FileInputStream fin = null;
1579
                fin = new FileInputStream(filename);
1580

    
1581
                //MIME type
1582
                String contentType = getServletContext().getMimeType(filename);
1583
                if (contentType == null) {
1584
                    ContentTypeProvider provider = new ContentTypeProvider(
1585
                            docid);
1586
                    contentType = provider.getContentType();
1587
                    logMetacat.info("Final contenttype is: "
1588
                            + contentType);
1589
                }
1590

    
1591
                response.setContentType(contentType);
1592
                // if we decide to use "application/octet-stream" for all data
1593
                // returns
1594
                // response.setContentType("application/octet-stream");
1595

    
1596
                try {
1597

    
1598
                    ServletOutputStream out = response.getOutputStream();
1599
                    byte[] buf = new byte[4 * 1024]; // 4K buffer
1600
                    int b = fin.read(buf);
1601
                    while (b != -1) {
1602
                        out.write(buf, 0, b);
1603
                        b = fin.read(buf);
1604
                    }
1605
                } finally {
1606
                    if (fin != null) fin.close();
1607
                }
1608

    
1609
            } else {
1610
                // this is metadata doc
1611
                if (qformat.equals("xml") || qformat.equals("")) {
1612
                    // if equals "", that means no qformat is specified. hence
1613
                    // by default the document should be returned in xml format
1614
                    // set content type first
1615
                    response.setContentType("text/xml"); //MIME type
1616
                    PrintWriter out = response.getWriter();
1617
                    doc.toXml(out, user, groups, withInlineData);
1618
                } else {
1619
                    response.setContentType("text/html"); //MIME type
1620
                    PrintWriter out = response.getWriter();
1621

    
1622
                    // Look up the document type
1623
                    String doctype = doc.getDoctype();
1624
                    // Transform the document to the new doctype
1625
                    DBTransform dbt = new DBTransform();
1626
                    dbt.transformXMLDocument(doc.toString(user, groups,
1627
                            withInlineData), doctype, "-//W3C//HTML//EN",
1628
                            qformat, out, params);
1629
                }
1630

    
1631
            }
1632
            EventLog.getInstance().log(request.getRemoteAddr(), user,
1633
                    docid, "read");
1634
        } catch (Exception except) {
1635
            throw except;
1636
        }
1637
    }
1638

    
1639
    /**
1640
     * read data from URLConnection
1641
     */
1642
    private void readFromURLConnection(HttpServletResponse response,
1643
            String docid) throws IOException, MalformedURLException
1644
    {
1645
        ServletOutputStream out = response.getOutputStream();
1646
        String contentType = getServletContext().getMimeType(docid); //MIME
1647
                                                                     // type
1648
        if (contentType == null) {
1649
            if (docid.endsWith(".xml")) {
1650
                contentType = "text/xml";
1651
            } else if (docid.endsWith(".css")) {
1652
                contentType = "text/css";
1653
            } else if (docid.endsWith(".dtd")) {
1654
                contentType = "text/plain";
1655
            } else if (docid.endsWith(".xsd")) {
1656
                contentType = "text/xml";
1657
            } else if (docid.endsWith("/")) {
1658
                contentType = "text/html";
1659
            } else {
1660
                File f = new File(docid);
1661
                if (f.isDirectory()) {
1662
                    contentType = "text/html";
1663
                } else {
1664
                    contentType = "application/octet-stream";
1665
                }
1666
            }
1667
        }
1668
        response.setContentType(contentType);
1669
        // if we decide to use "application/octet-stream" for all data returns
1670
        // response.setContentType("application/octet-stream");
1671

    
1672
        // this is http url
1673
        URL url = new URL(docid);
1674
        BufferedInputStream bis = null;
1675
        try {
1676
            bis = new BufferedInputStream(url.openStream());
1677
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1678
            int b = bis.read(buf);
1679
            while (b != -1) {
1680
                out.write(buf, 0, b);
1681
                b = bis.read(buf);
1682
            }
1683
        } finally {
1684
            if (bis != null) bis.close();
1685
        }
1686

    
1687
    }
1688

    
1689
    /**
1690
     * read file/doc and write to ZipOutputStream
1691
     *
1692
     * @param docid
1693
     * @param zout
1694
     * @param user
1695
     * @param groups
1696
     * @throws ClassNotFoundException
1697
     * @throws IOException
1698
     * @throws SQLException
1699
     * @throws McdbException
1700
     * @throws Exception
1701
     */
1702
    private void addDocToZip(HttpServletRequest request, String docid,
1703
            ZipOutputStream zout, String user, String[] groups) throws
1704
            ClassNotFoundException, IOException, SQLException, McdbException,
1705
            Exception
1706
    {
1707
        byte[] bytestring = null;
1708
        ZipEntry zentry = null;
1709

    
1710
        try {
1711
            URL url = new URL(docid);
1712

    
1713
            // this http url; read from URLConnection; add to zip
1714
            zentry = new ZipEntry(docid);
1715
            zout.putNextEntry(zentry);
1716
            BufferedInputStream bis = null;
1717
            try {
1718
                bis = new BufferedInputStream(url.openStream());
1719
                byte[] buf = new byte[4 * 1024]; // 4K buffer
1720
                int b = bis.read(buf);
1721
                while (b != -1) {
1722
                    zout.write(buf, 0, b);
1723
                    b = bis.read(buf);
1724
                }
1725
            } finally {
1726
                if (bis != null) bis.close();
1727
            }
1728
            zout.closeEntry();
1729

    
1730
        } catch (MalformedURLException mue) {
1731

    
1732
            // this is metacat doc (data file or metadata doc)
1733
            try {
1734
                DocumentImpl doc = new DocumentImpl(docid);
1735

    
1736
                //check the permission for read
1737
                if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1738
                    Exception e = new Exception("User " + user
1739
                            + " does not have "
1740
                            + "permission to read the document with the docid "
1741
                            + docid);
1742
                    throw e;
1743
                }
1744

    
1745
                if (doc.getRootNodeID() == 0) {
1746
                    // this is data file; add file to zip
1747
                    String filepath = MetaCatUtil.getOption("datafilepath");
1748
                    if (!filepath.endsWith("/")) {
1749
                        filepath += "/";
1750
                    }
1751
                    String filename = filepath + docid;
1752
                    FileInputStream fin = null;
1753
                    fin = new FileInputStream(filename);
1754
                    try {
1755

    
1756
                        zentry = new ZipEntry(docid);
1757
                        zout.putNextEntry(zentry);
1758
                        byte[] buf = new byte[4 * 1024]; // 4K buffer
1759
                        int b = fin.read(buf);
1760
                        while (b != -1) {
1761
                            zout.write(buf, 0, b);
1762
                            b = fin.read(buf);
1763
                        }
1764
                    } finally {
1765
                        if (fin != null) fin.close();
1766
                    }
1767
                    zout.closeEntry();
1768

    
1769
                } else {
1770
                    // this is metadata doc; add doc to zip
1771
                    bytestring = doc.toString().getBytes();
1772
                    zentry = new ZipEntry(docid + ".xml");
1773
                    zentry.setSize(bytestring.length);
1774
                    zout.putNextEntry(zentry);
1775
                    zout.write(bytestring, 0, bytestring.length);
1776
                    zout.closeEntry();
1777
                }
1778
                EventLog.getInstance().log(request.getRemoteAddr(), user,
1779
                        docid, "read");
1780
            } catch (Exception except) {
1781
                throw except;
1782
            }
1783
        }
1784
    }
1785

    
1786
    /**
1787
     * If metacat couldn't find a data file or document locally, it will read
1788
     * this docid from its home server. This is for the replication feature
1789
     */
1790
    private void readFromRemoteMetaCat(HttpServletResponse response,
1791
            String docid, String rev, String user, String password,
1792
            ServletOutputStream out, boolean zip, ZipOutputStream zout)
1793
            throws Exception
1794
    {
1795
        // Create a object of RemoteDocument, "" is for zipEntryPath
1796
        RemoteDocument remoteDoc = new RemoteDocument(docid, rev, user,
1797
                password, "");
1798
        String docType = remoteDoc.getDocType();
1799
        // Only read data file
1800
        if (docType.equals("BIN")) {
1801
            // If it is zip format
1802
            if (zip) {
1803
                remoteDoc.readDocumentFromRemoteServerByZip(zout);
1804
            } else {
1805
                if (out == null) {
1806
                    out = response.getOutputStream();
1807
                }
1808
                response.setContentType("application/octet-stream");
1809
                remoteDoc.readDocumentFromRemoteServer(out);
1810
            }
1811
        } else {
1812
            throw new Exception("Docid: " + docid + "." + rev
1813
                    + " couldn't find");
1814
        }
1815
    }
1816

    
1817
    /**
1818
     * Handle the database putdocument request and write an XML document to the
1819
     * database connection
1820
     */
1821
    private void handleInsertOrUpdateAction(HttpServletRequest request,
1822
            HttpServletResponse response, PrintWriter out, Hashtable params,
1823
            String user, String[] groups)
1824
    {
1825
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1826
        DBConnection dbConn = null;
1827
        int serialNumber = -1;
1828

    
1829
        if(params.get("docid") == null){
1830
            out.println("<?xml version=\"1.0\"?>");
1831
            out.println("<error>");
1832
            out.println("Docid not specified");
1833
            out.println("</error>");
1834
            logMetacat.error("Docid not specified");
1835
            return;
1836
        }
1837
        
1838
        if(!MetaCatUtil.canInsertOrUpdate(user, groups)){
1839
        	out.println("<?xml version=\"1.0\"?>");
1840
            out.println("<error>");
1841
            out.println("User '" + user + "' not allowed to insert and update");
1842
            out.println("</error>");
1843
            logMetacat.error("User '" + user + "' not allowed to insert and update");
1844
            return;
1845
        }
1846

    
1847
        try {
1848
            // Get the document indicated
1849
            String[] doctext = (String[]) params.get("doctext");
1850
            String pub = null;
1851
            if (params.containsKey("public")) {
1852
                pub = ((String[]) params.get("public"))[0];
1853
            }
1854

    
1855
            StringReader dtd = null;
1856
            if (params.containsKey("dtdtext")) {
1857
                String[] dtdtext = (String[]) params.get("dtdtext");
1858
                try {
1859
                    if (!dtdtext[0].equals("")) {
1860
                        dtd = new StringReader(dtdtext[0]);
1861
                    }
1862
                } catch (NullPointerException npe) {
1863
                }
1864
            }
1865

    
1866
            if(doctext == null){
1867
                out.println("<?xml version=\"1.0\"?>");
1868
                out.println("<error>");
1869
                out.println("Document text not submitted");
1870
                out.println("</error>");
1871
                return;
1872
            }
1873

    
1874
            StringReader xml = new StringReader(doctext[0]);
1875
            boolean validate = false;
1876
            DocumentImplWrapper documentWrapper = null;
1877
            try {
1878
                // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ...
1879
                // >
1880
                // in order to decide whether to use validation parser
1881
                validate = needDTDValidation(xml);
1882
                if (validate) {
1883
                    // set a dtd base validation parser
1884
                    String rule = DocumentImpl.DTD;
1885
                    documentWrapper = new DocumentImplWrapper(rule, validate);
1886
                } else {
1887

    
1888
                    String namespace = findNamespace(xml);
1889
                    
1890
                	if (namespace != null) {
1891
                		if (namespace.compareTo(DocumentImpl.EML2_0_0NAMESPACE) == 0
1892
                				|| namespace.compareTo(
1893
                				DocumentImpl.EML2_0_1NAMESPACE) == 0) {
1894
                			// set eml2 base	 validation parser
1895
                			String rule = DocumentImpl.EML200;
1896
                			// using emlparser to check id validation
1897
                			EMLParser parser = new EMLParser(doctext[0]);
1898
                			documentWrapper = new DocumentImplWrapper(rule, true);
1899
                		} else if (namespace.compareTo(
1900
                                DocumentImpl.EML2_1_0NAMESPACE) == 0) {
1901
                			// set eml2 base validation parser
1902
                			String rule = DocumentImpl.EML210;
1903
                			// using emlparser to check id validation
1904
                			EMLParser parser = new EMLParser(doctext[0]);
1905
                			documentWrapper = new DocumentImplWrapper(rule, true);
1906
                		} else {
1907
                			// set schema base validation parser
1908
                			String rule = DocumentImpl.SCHEMA;
1909
                			documentWrapper = new DocumentImplWrapper(rule, true);
1910
                		}
1911
                	} else {
1912
                		documentWrapper = new DocumentImplWrapper("", false);
1913
                	}
1914
                }
1915

    
1916
                String[] action = (String[]) params.get("action");
1917
                String[] docid = (String[]) params.get("docid");
1918
                String newdocid = null;
1919

    
1920
                String doAction = null;
1921
                if (action[0].equals("insert")) {
1922
                    doAction = "INSERT";
1923
                } else if (action[0].equals("update")) {
1924
                    doAction = "UPDATE";
1925
                }
1926

    
1927
                try {
1928
                    // get a connection from the pool
1929
                    dbConn = DBConnectionPool
1930
                            .getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1931
                    serialNumber = dbConn.getCheckOutSerialNumber();
1932

    
1933
                    // write the document to the database
1934
                    try {
1935
                        String accNumber = docid[0];
1936
                        logMetacat.debug("" + doAction + " "
1937
                                + accNumber + "...");
1938
                        if (accNumber.equals("")) {
1939
                            accNumber = null;
1940
                        }
1941
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1942
                                doAction, accNumber, user, groups);
1943
                        EventLog.getInstance().log(request.getRemoteAddr(),
1944
                                user, accNumber, action[0]);
1945
                    } catch (NullPointerException npe) {
1946
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1947
                                doAction, null, user, groups);
1948
                        EventLog.getInstance().log(request.getRemoteAddr(),
1949
                                user, "", action[0]);
1950
                    }
1951
                }
1952
                finally {
1953
                    // Return db connection
1954
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1955
                }
1956

    
1957
                // set content type and other response header fields first
1958
                //response.setContentType("text/xml");
1959
                out.println("<?xml version=\"1.0\"?>");
1960
                out.println("<success>");
1961
                out.println("<docid>" + newdocid + "</docid>");
1962
                out.println("</success>");
1963

    
1964
            } catch (NullPointerException npe) {
1965
                //response.setContentType("text/xml");
1966
                out.println("<?xml version=\"1.0\"?>");
1967
                out.println("<error>");
1968
                out.println(npe.getMessage());
1969
                out.println("</error>");
1970
                logMetacat.warn("Error in writing eml document to the database" + npe.getMessage());
1971
                npe.printStackTrace();
1972
            }
1973
        } catch (Exception e) {
1974
            //response.setContentType("text/xml");
1975
            out.println("<?xml version=\"1.0\"?>");
1976
            out.println("<error>");
1977
            out.println(e.getMessage());
1978
            out.println("</error>");
1979
            logMetacat.warn("Error in writing eml document to the database" + e.getMessage());
1980
            e.printStackTrace();
1981
        }
1982
    }
1983

    
1984
    /**
1985
     * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > in
1986
     * order to decide whether to use validation parser
1987
     */
1988
    private static boolean needDTDValidation(StringReader xmlreader)
1989
            throws IOException
1990
    {
1991
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1992
        StringBuffer cbuff = new StringBuffer();
1993
        java.util.Stack st = new java.util.Stack();
1994
        boolean validate = false;
1995
        int c;
1996
        int inx;
1997

    
1998
        // read from the stream until find the keywords
1999
        while ((st.empty() || st.size() < 4) && ((c = xmlreader.read()) != -1)) {
2000
            cbuff.append((char) c);
2001

    
2002
            // "<!DOCTYPE" keyword is found; put it in the stack
2003
            if ((inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1) {
2004
                cbuff = new StringBuffer();
2005
                st.push("<!DOCTYPE");
2006
            }
2007
            // "PUBLIC" keyword is found; put it in the stack
2008
            if ((inx = cbuff.toString().indexOf("PUBLIC")) != -1) {
2009
                cbuff = new StringBuffer();
2010
                st.push("PUBLIC");
2011
            }
2012
            // "SYSTEM" keyword is found; put it in the stack
2013
            if ((inx = cbuff.toString().indexOf("SYSTEM")) != -1) {
2014
                cbuff = new StringBuffer();
2015
                st.push("SYSTEM");
2016
            }
2017
            // ">" character is found; put it in the stack
2018
            // ">" is found twice: fisrt from <?xml ...?>
2019
            // and second from <!DOCTYPE ... >
2020
            if ((inx = cbuff.toString().indexOf(">")) != -1) {
2021
                cbuff = new StringBuffer();
2022
                st.push(">");
2023
            }
2024
        }
2025

    
2026
        // close the stream
2027
        xmlreader.reset();
2028

    
2029
        // check the stack whether it contains the keywords:
2030
        // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
2031
        if (st.size() == 4) {
2032
            if (((String) st.pop()).equals(">")
2033
                    && (((String) st.peek()).equals("PUBLIC") | ((String) st
2034
                            .pop()).equals("SYSTEM"))
2035
                    && ((String) st.pop()).equals("<!DOCTYPE")) {
2036
                validate = true;
2037
            }
2038
        }
2039

    
2040
        logMetacat.info("Validation for dtd is " + validate);
2041
        return validate;
2042
    }
2043

    
2044
    // END OF INSERT/UPDATE SECTION
2045

    
2046
    /* check if the xml string contains key words to specify schema loocation */
2047
    private String findNamespace(StringReader xml) throws IOException
2048
    {
2049
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2050
        String namespace = null;
2051

    
2052
        String eml2_0_0NameSpace = DocumentImpl.EML2_0_0NAMESPACE;
2053
        String eml2_0_1NameSpace = DocumentImpl.EML2_0_1NAMESPACE;
2054
        String eml2_1_0NameSpace = DocumentImpl.EML2_1_0NAMESPACE;
2055

    
2056
        if (xml == null) {
2057
            logMetacat.debug("Validation for schema is "
2058
                    + namespace);
2059
            return namespace;
2060
        }
2061
        String targetLine = getSchemaLine(xml);
2062
		
2063
        if (targetLine != null) {
2064

    
2065
        	// find if the root element has prefix
2066
        	String prefix = getPrefix(targetLine);
2067
        	logMetacat.info("prefix is:" + prefix);
2068
        	int startIndex = 0;
2069
        	
2070
        	
2071
        	if(prefix != null)
2072
        	{
2073
        		// if prefix found then look for xmlns:prefix
2074
        		// element to find the ns 
2075
        		String namespaceWithPrefix = NAMESPACEKEYWORD 
2076
        					+ ":" + prefix;
2077
        		startIndex = targetLine.indexOf(namespaceWithPrefix);
2078
            	logMetacat.debug("namespaceWithPrefix is:" + namespaceWithPrefix+":");
2079
            	logMetacat.debug("startIndex is:" + startIndex);
2080
        		
2081
        	} else {
2082
        		// if prefix not found then look for xmlns
2083
        		// attribute to find the ns 
2084
        		startIndex = targetLine.indexOf(NAMESPACEKEYWORD);
2085
            	logMetacat.debug("startIndex is:" + startIndex);
2086
        	}
2087
        		
2088
            int start = 1;
2089
            int end = 1;
2090
            String namespaceString = null;
2091
            int count = 0;
2092
            if (startIndex != -1) {
2093
                for (int i = startIndex; i < targetLine.length(); i++) {
2094
                    if (targetLine.charAt(i) == '"') {
2095
                        count++;
2096
                    }
2097
                    if (targetLine.charAt(i) == '"' && count == 1) {
2098
                        start = i;
2099
                    }
2100
                    if (targetLine.charAt(i) == '"' && count == 2) {
2101
                        end = i;
2102
                        break;
2103
                    }
2104
                }
2105
            } 
2106
            // else: xmlns not found. namespace = null will be returned
2107

    
2108
         	logMetacat.debug("targetLine is " + targetLine);
2109
         	logMetacat.debug("start is " + end);
2110
         	logMetacat.debug("end is " + end);
2111
           
2112
            if(start < end){
2113
            	namespaceString = targetLine.substring(start + 1, end);
2114
            	logMetacat.debug("namespaceString is " + namespaceString);
2115
            }
2116
            logMetacat.debug("namespace in xml is: "
2117
                    + namespaceString);
2118
            if(namespaceString != null){
2119
            	if (namespaceString.indexOf(eml2_0_0NameSpace) != -1) {
2120
            		namespace = eml2_0_0NameSpace;
2121
            	} else if (namespaceString.indexOf(eml2_0_1NameSpace) != -1) {
2122
            		namespace = eml2_0_1NameSpace;
2123
            	} else if (namespaceString.indexOf(eml2_1_0NameSpace) != -1) {
2124
            		namespace = eml2_1_0NameSpace;
2125
            	} else {
2126
            		namespace = namespaceString;
2127
            	}
2128
            }
2129
        }
2130

    
2131
        logMetacat.debug("Validation for eml is " + namespace);
2132

    
2133
        return namespace;
2134

    
2135
    }
2136

    
2137
    private String getSchemaLine(StringReader xml) throws IOException
2138
    {
2139
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2140
        // find the line
2141
        String secondLine = null;
2142
        int count = 0;
2143
        int endIndex = 0;
2144
        int startIndex = 0;
2145
        final int TARGETNUM = 1;
2146
        StringBuffer buffer = new StringBuffer();
2147
        boolean comment = false;
2148
        boolean processingInstruction = false;
2149
        char thirdPreviousCharacter = '?';
2150
        char secondPreviousCharacter = '?';
2151
        char previousCharacter = '?';
2152
        char currentCharacter = '?';
2153
        int tmp = xml.read();
2154
        while (tmp != -1) {
2155
            currentCharacter = (char)tmp;
2156
            //in a comment
2157
            if (currentCharacter == '-' && previousCharacter == '-'
2158
                    && secondPreviousCharacter == '!'
2159
                    && thirdPreviousCharacter == '<') {
2160
                comment = true;
2161
            }
2162
            //out of comment
2163
            if (comment && currentCharacter == '>' && previousCharacter == '-'
2164
                    && secondPreviousCharacter == '-') {
2165
                comment = false;
2166
            }
2167

    
2168
            //in a processingInstruction
2169
            if (currentCharacter == '?' && previousCharacter == '<') {
2170
            	processingInstruction = true;
2171
            }
2172
            
2173
            //out of processingInstruction
2174
            if (processingInstruction && currentCharacter == '>' 
2175
            	&& previousCharacter == '?') {
2176
            	processingInstruction = false;
2177
            }
2178
            
2179
            //this is not comment or a processingInstruction
2180
            if (currentCharacter != '!' && previousCharacter == '<' 
2181
            	&& !comment && !processingInstruction) {
2182
                count++;
2183
            }
2184
            
2185
            // get target line
2186
            if (count == TARGETNUM && currentCharacter != '>') {
2187
                buffer.append(currentCharacter);
2188
            }
2189
            if (count == TARGETNUM && currentCharacter == '>') {
2190
                break;
2191
            }
2192
            thirdPreviousCharacter = secondPreviousCharacter;
2193
            secondPreviousCharacter = previousCharacter;
2194
            previousCharacter = currentCharacter;
2195
            tmp = xml.read();
2196
        }
2197
        secondLine = buffer.toString();
2198
        logMetacat.debug("the second line string is: " + secondLine);
2199
        
2200
        xml.reset();
2201
        return secondLine;
2202
    }
2203

    
2204
    private String getPrefix(String schemaLine)
2205
    {
2206
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2207
        String prefix = null;
2208
        
2209
        if(schemaLine.indexOf(" ") > 0){
2210
            String rootElement = "";
2211
            try {
2212
                rootElement = schemaLine.substring(0, schemaLine.indexOf(" "));
2213
            } catch (StringIndexOutOfBoundsException sioobe) {
2214
                rootElement = schemaLine;
2215
            }
2216

    
2217
            logMetacat.debug("rootElement:" + rootElement);
2218
        
2219
            if(rootElement.indexOf(":") > 0){
2220
                prefix = rootElement.substring(rootElement.indexOf(":") + 1,
2221
                    rootElement.length());
2222
            }
2223
            
2224
            if(prefix != null){
2225
                return prefix.trim();
2226
            }
2227
        }
2228
        return null;
2229
    }
2230

    
2231
    /**
2232
     * Handle the database delete request and delete an XML document from the
2233
     * database connection
2234
     */
2235
    private void handleDeleteAction(PrintWriter out, Hashtable params,
2236
            HttpServletRequest request, HttpServletResponse response,
2237
            String user, String[] groups)
2238
    {
2239
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2240
        String[] docid = (String[]) params.get("docid");
2241

    
2242
        if(docid == null){
2243
          response.setContentType("text/xml");
2244
          out.println("<?xml version=\"1.0\"?>");
2245
          out.println("<error>");
2246
          out.println("Docid not specified.");
2247
          out.println("</error>");
2248
          logMetacat.error("Docid not specified for the document to be deleted.");
2249
        } else {
2250

    
2251
            // delete the document from the database
2252
            try {
2253

    
2254
                try {
2255
                    // null means notify server is null
2256
                    DocumentImpl.delete(docid[0], user, groups, null);
2257
                    EventLog.getInstance().log(request.getRemoteAddr(),
2258
                                               user, docid[0], "delete");
2259
                    response.setContentType("text/xml");
2260
                    out.println("<?xml version=\"1.0\"?>");
2261
                    out.println("<success>");
2262
                    out.println("Document deleted.");
2263
                    out.println("</success>");
2264
                    logMetacat.info("Document deleted.");
2265

    
2266
                    // Delete from spatial cache
2267
                    SpatialHarvester sh = new SpatialHarvester();
2268
                    sh.addToDeleteQue( MetaCatUtil.getSmartDocId( docid[0] ) );
2269
                    sh.destroy();
2270

    
2271
                }
2272
                catch (AccessionNumberException ane) {
2273
                    response.setContentType("text/xml");
2274
                    out.println("<?xml version=\"1.0\"?>");
2275
                    out.println("<error>");
2276
                    //out.println("Error deleting document!!!");
2277
                    out.println(ane.getMessage());
2278
                    out.println("</error>");
2279
                    logMetacat.error("Document could not be deleted: " 
2280
                    		+ ane.getMessage());
2281
                }
2282
            }
2283
            catch (Exception e) {
2284
                response.setContentType("text/xml");
2285
                out.println("<?xml version=\"1.0\"?>");
2286
                out.println("<error>");
2287
                out.println(e.getMessage());
2288
                out.println("</error>");
2289
                logMetacat.error("Document could not be deleted: " 
2290
                		+ e.getMessage());
2291
            }
2292
        }
2293
    }
2294

    
2295
    /**
2296
     * Handle the validation request and return the results to the requestor
2297
     */
2298
    private void handleValidateAction(PrintWriter out, Hashtable params)
2299
    {
2300

    
2301
        // Get the document indicated
2302
        String valtext = null;
2303
        DBConnection dbConn = null;
2304
        int serialNumber = -1;
2305

    
2306
        try {
2307
            valtext = ((String[]) params.get("valtext"))[0];
2308
        } catch (Exception nullpe) {
2309

    
2310
            String docid = null;
2311
            try {
2312
                // Find the document id number
2313
                docid = ((String[]) params.get("docid"))[0];
2314

    
2315
                // Get the document indicated from the db
2316
                DocumentImpl xmldoc = new DocumentImpl(docid);
2317
                valtext = xmldoc.toString();
2318

    
2319
            } catch (NullPointerException npe) {
2320

    
2321
                out.println("<error>Error getting document ID: " + docid
2322
                        + "</error>");
2323
                //if ( conn != null ) { util.returnConnection(conn); }
2324
                return;
2325
            } catch (Exception e) {
2326

    
2327
                out.println(e.getMessage());
2328
            }
2329
        }
2330

    
2331
        try {
2332
            // get a connection from the pool
2333
            dbConn = DBConnectionPool
2334
                    .getDBConnection("MetaCatServlet.handleValidateAction");
2335
            serialNumber = dbConn.getCheckOutSerialNumber();
2336
            DBValidate valobj = new DBValidate(dbConn);
2337
            boolean valid = valobj.validateString(valtext);
2338

    
2339
            // set content type and other response header fields first
2340

    
2341
            out.println(valobj.returnErrors());
2342

    
2343
        } catch (NullPointerException npe2) {
2344
            // set content type and other response header fields first
2345

    
2346
            out.println("<error>Error validating document.</error>");
2347
        } catch (Exception e) {
2348

    
2349
            out.println(e.getMessage());
2350
        } finally {
2351
            // Return db connection
2352
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2353
        }
2354
    }
2355

    
2356
    /**
2357
     * Handle "getrevsionanddoctype" action Given a docid, return it's current
2358
     * revision and doctype from data base The output is String look like
2359
     * "rev;doctype"
2360
     */
2361
    private void handleGetRevisionAndDocTypeAction(PrintWriter out,
2362
            Hashtable params)
2363
    {
2364
        // To store doc parameter
2365
        String[] docs = new String[10];
2366
        // Store a single doc id
2367
        String givenDocId = null;
2368
        // Get docid from parameters
2369
        if (params.containsKey("docid")) {
2370
            docs = (String[]) params.get("docid");
2371
        }
2372
        // Get first docid form string array
2373
        givenDocId = docs[0];
2374

    
2375
        try {
2376
            // Make sure there is a docid
2377
            if (givenDocId == null || givenDocId.equals("")) { throw new Exception(
2378
                    "User didn't specify docid!"); }//if
2379

    
2380
            // Create a DBUtil object
2381
            DBUtil dbutil = new DBUtil();
2382
            // Get a rev and doctype
2383
            String revAndDocType = dbutil
2384
                    .getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
2385
            out.println(revAndDocType);
2386

    
2387
        } catch (Exception e) {
2388
            // Handle exception
2389
            out.println("<?xml version=\"1.0\"?>");
2390
            out.println("<error>");
2391
            out.println(e.getMessage());
2392
            out.println("</error>");
2393
        }
2394

    
2395
    }
2396

    
2397
    /**
2398
     * Handle "getaccesscontrol" action. Read Access Control List from db
2399
     * connection in XML format
2400
     */
2401
    private void handleGetAccessControlAction(PrintWriter out,
2402
            Hashtable params, HttpServletResponse response, String username,
2403
            String[] groupnames)
2404
    {
2405
        DBConnection dbConn = null;
2406
        int serialNumber = -1;
2407
        String docid = ((String[]) params.get("docid"))[0];
2408

    
2409
        try {
2410

    
2411
            // get connection from the pool
2412
            dbConn = DBConnectionPool
2413
                    .getDBConnection("MetaCatServlet.handleGetAccessControlAction");
2414
            serialNumber = dbConn.getCheckOutSerialNumber();
2415
            AccessControlList aclobj = new AccessControlList(dbConn);
2416
            String acltext = aclobj.getACL(docid, username, groupnames);
2417
            out.println(acltext);
2418

    
2419
        } catch (Exception e) {
2420
            out.println("<?xml version=\"1.0\"?>");
2421
            out.println("<error>");
2422
            out.println(e.getMessage());
2423
            out.println("</error>");
2424
        } finally {
2425
            // Retrun db connection to pool
2426
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2427
        }
2428
    }
2429

    
2430
    /**
2431
     * Handle the "getprincipals" action. Read all principals from
2432
     * authentication scheme in XML format
2433
     */
2434
    private void handleGetPrincipalsAction(PrintWriter out, String user,
2435
            String password)
2436
    {
2437
        try {
2438
            AuthSession auth = new AuthSession();
2439
            String principals = auth.getPrincipals(user, password);
2440
            out.println(principals);
2441

    
2442
        } catch (Exception e) {
2443
            out.println("<?xml version=\"1.0\"?>");
2444
            out.println("<error>");
2445
            out.println(e.getMessage());
2446
            out.println("</error>");
2447
        }
2448
    }
2449

    
2450
    /**
2451
     * Handle "getdoctypes" action. Read all doctypes from db connection in XML
2452
     * format
2453
     */
2454
    private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
2455
            HttpServletResponse response)
2456
    {
2457
        try {
2458
            DBUtil dbutil = new DBUtil();
2459
            String doctypes = dbutil.readDoctypes();
2460
            out.println(doctypes);
2461
        } catch (Exception e) {
2462
            out.println("<?xml version=\"1.0\"?>");
2463
            out.println("<error>");
2464
            out.println(e.getMessage());
2465
            out.println("</error>");
2466
        }
2467
    }
2468

    
2469
    /**
2470
     * Handle the "getdtdschema" action. Read DTD or Schema file for a given
2471
     * doctype from Metacat catalog system
2472
     */
2473
    private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
2474
            HttpServletResponse response)
2475
    {
2476

    
2477
        String doctype = null;
2478
        String[] doctypeArr = (String[]) params.get("doctype");
2479

    
2480
        // get only the first doctype specified in the list of doctypes
2481
        // it could be done for all doctypes in that list
2482
        if (doctypeArr != null) {
2483
            doctype = ((String[]) params.get("doctype"))[0];
2484
        }
2485

    
2486
        try {
2487
            DBUtil dbutil = new DBUtil();
2488
            String dtdschema = dbutil.readDTDSchema(doctype);
2489
            out.println(dtdschema);
2490

    
2491
        } catch (Exception e) {
2492
            out.println("<?xml version=\"1.0\"?>");
2493
            out.println("<error>");
2494
            out.println(e.getMessage());
2495
            out.println("</error>");
2496
        }
2497

    
2498
    }
2499

    
2500
    /**
2501
     * Handle the "getlastdocid" action. Get the latest docid with rev number
2502
     * from db connection in XML format
2503
     */
2504
    private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
2505
            HttpServletResponse response)
2506
    {
2507

    
2508
        String scope = ((String[]) params.get("scope"))[0];
2509
        if (scope == null) {
2510
            scope = ((String[]) params.get("username"))[0];
2511
        }
2512

    
2513
        try {
2514

    
2515
            DBUtil dbutil = new DBUtil();
2516
            String lastDocid = dbutil.getMaxDocid(scope);
2517
            out.println("<?xml version=\"1.0\"?>");
2518
            out.println("<lastDocid>");
2519
            out.println("  <scope>" + scope + "</scope>");
2520
            out.println("  <docid>" + lastDocid + "</docid>");
2521
            out.println("</lastDocid>");
2522

    
2523
        } catch (Exception e) {
2524
            out.println("<?xml version=\"1.0\"?>");
2525
            out.println("<error>");
2526
            out.println(e.getMessage());
2527
            out.println("</error>");
2528
        }
2529
    }
2530

    
2531
    /**
2532
     * Print a report from the event log based on filter parameters passed in
2533
     * from the web.
2534
     *
2535
     * @param params the parameters from the web request
2536
     * @param request the http request object for getting request details
2537
     * @param response the http response object for writing output
2538
     */
2539
    private void handleGetLogAction(Hashtable params, HttpServletRequest request,
2540
            HttpServletResponse response, String username, String[] groups)
2541
    {
2542
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2543
        try {
2544
            response.setContentType("text/xml");
2545
            PrintWriter out = response.getWriter();
2546

    
2547
            // Check that the user is authenticated as an administrator account
2548
            if (!MetaCatUtil.isAdministrator(username, groups)) {
2549
                out.print("<error>");
2550
                out.print("The user \"" + username +
2551
                        "\" is not authorized for this action.");
2552
                out.print("</error>");
2553
                return;
2554
            }
2555

    
2556
            // Get all of the parameters in the correct formats
2557
            String[] ipAddress = (String[])params.get("ipaddress");
2558
            String[] principal = (String[])params.get("principal");
2559
            String[] docid = (String[])params.get("docid");
2560
            String[] event = (String[])params.get("event");
2561
            String[] startArray = (String[]) params.get("start");
2562
            String[] endArray = (String[]) params.get("end");
2563
            String start = null;
2564
            String end = null;
2565
            if (startArray != null) {
2566
                start = startArray[0];
2567
            }
2568
            if (endArray != null) {
2569
                end = endArray[0];
2570
            }
2571
            Timestamp startDate = null;
2572
            Timestamp endDate = null;
2573
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
2574
            try {
2575
                if (start != null) {
2576
                    startDate = new Timestamp((format.parse(start)).getTime());
2577
                }
2578
                if (end != null) {
2579
                    endDate = new Timestamp((format.parse(end)).getTime());
2580
                }
2581
            } catch (ParseException e) {
2582
                System.out.println("Failed to created Timestamp from input.");
2583
            }
2584

    
2585
            // Request the report by passing the filter parameters
2586
            out.println(EventLog.getInstance().getReport(ipAddress, principal,
2587
                    docid, event, startDate, endDate));
2588
            out.close();
2589
        } catch (IOException e) {
2590
            logMetacat.error(
2591
                    "Could not open http response for writing: " + e.getMessage());
2592
        }
2593
    }
2594

    
2595
    /**
2596
     * Rebuild the index for one or more documents. If the docid parameter is
2597
     * provided, rebuild for just that one document or list of documents. If
2598
     * not, then rebuild the index for all documents in the xml_documents
2599
     * table.
2600
     *
2601
     * @param params the parameters from the web request
2602
     * @param request the http request object for getting request details
2603
     * @param response the http response object for writing output
2604
     * @param username the username of the authenticated user
2605
     */
2606
    private void handleBuildIndexAction(Hashtable params,
2607
            HttpServletRequest request, HttpServletResponse response,
2608
            String username, String[] groups)
2609
    {
2610
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2611
        
2612
        // Get all of the parameters in the correct formats
2613
        String[] docid = (String[])params.get("docid");
2614

    
2615
        // Rebuild the indices for appropriate documents
2616
        try {
2617
            response.setContentType("text/xml");
2618
            PrintWriter out = response.getWriter();
2619

    
2620
            // Check that the user is authenticated as an administrator account
2621
            if (!MetaCatUtil.isAdministrator(username, groups)) {
2622
                out.print("<error>");
2623
                out.print("The user \"" + username +
2624
                        "\" is not authorized for this action.");
2625
                out.print("</error>");
2626
                return;
2627
            }
2628

    
2629
            // Process the documents
2630
            out.println("<success>");
2631
            if (docid == null || docid.length == 0) {
2632
                // Process all of the documents
2633
                try {
2634
                    Vector documents = getDocumentList();
2635
                    Iterator it = documents.iterator();
2636
                    while (it.hasNext()) {
2637
                        String id = (String) it.next();
2638
                        buildDocumentIndex(id, out);
2639
                    }
2640
                } catch (SQLException se) {
2641
                    out.print("<error>");
2642
                    out.print(se.getMessage());
2643
                    out.println("</error>");
2644
                }
2645
            } else {
2646
                // Only process the requested documents
2647
                for (int i = 0; i < docid.length; i++) {
2648
                    buildDocumentIndex(docid[i], out);
2649
                }
2650
            }
2651
            out.println("</success>");
2652
            out.close();
2653
        } catch (IOException e) {
2654
            logMetacat.error(
2655
                    "Could not open http response for writing: "
2656
                    + e.getMessage());
2657
        }
2658
    }
2659

    
2660
    /**
2661
     * Build the index for one document by reading the document and
2662
     * calling its buildIndex() method.
2663
     *
2664
     * @param docid the document (with revision) to rebuild
2665
     * @param out the PrintWriter to which output is printed
2666
     */
2667
    private void buildDocumentIndex(String docid, PrintWriter out)
2668
    {
2669
        try {
2670
            DocumentImpl doc = new DocumentImpl(docid, false);
2671
            doc.buildIndex();
2672
            out.print("<docid>" + docid);
2673
            out.println("</docid>");
2674
        } catch (McdbException me) {
2675
            out.print("<error>");
2676
            out.print(me.getMessage());
2677
            out.println("</error>");
2678
        }
2679
    }
2680

    
2681
    /**
2682
     * Handle documents passed to metacat that are encoded using the
2683
     * "multipart/form-data" mime type. This is typically used for uploading
2684
     * data files which may be binary and large.
2685
     */
2686
    private void handleMultipartForm(HttpServletRequest request,
2687
            HttpServletResponse response)
2688
    {
2689
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2690
        PrintWriter out = null;
2691
        String action = null;
2692

    
2693
        // Parse the multipart form, and save the parameters in a Hashtable and
2694
        // save the FileParts in a hashtable
2695

    
2696
        Hashtable params = new Hashtable();
2697
        Hashtable fileList = new Hashtable();
2698
        int sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit")))
2699
                .intValue();
2700
        logMetacat.info(
2701
                "The size limit of uploaded data files is: " + sizeLimit);
2702

    
2703
        try {
2704
            MultipartParser mp = new MultipartParser(request,
2705
                    sizeLimit * 1024 * 1024);
2706
            Part part;
2707
            while ((part = mp.readNextPart()) != null) {
2708
                String name = part.getName();
2709

    
2710
                if (part.isParam()) {
2711
                    // it's a parameter part
2712
                    ParamPart paramPart = (ParamPart) part;
2713
                    String value = paramPart.getStringValue();
2714
                    params.put(name, value);
2715
                    if (name.equals("action")) {
2716
                        action = value;
2717
                    }
2718
                } else if (part.isFile()) {
2719
                    // it's a file part
2720
                    FilePart filePart = (FilePart) part;
2721
                    fileList.put(name, filePart);
2722

    
2723
                    // Stop once the first file part is found, otherwise going
2724
                    // onto the
2725
                    // next part prevents access to the file contents. So...for
2726
                    // upload
2727
                    // to work, the datafile must be the last part
2728
                    break;
2729
                }
2730
            }
2731
        } catch (IOException ioe) {
2732
            try {
2733
                out = response.getWriter();
2734
            } catch (IOException ioe2) {
2735
                logMetacat.fatal("Fatal Error: couldn't get response output stream.");
2736
            }
2737
            out.println("<?xml version=\"1.0\"?>");
2738
            out.println("<error>");
2739
            out.println("Error: problem reading multipart data.");
2740
            out.println("</error>");
2741
        }
2742

    
2743
        // Get the session information
2744
        String username = null;
2745
        String password = null;
2746
        String[] groupnames = null;
2747
        String sess_id = null;
2748

    
2749
        // be aware of session expiration on every request
2750
        HttpSession sess = request.getSession(true);
2751
        if (sess.isNew()) {
2752
            // session expired or has not been stored b/w user requests
2753
            username = "public";
2754
            sess.setAttribute("username", username);
2755
        } else {
2756
            username = (String) sess.getAttribute("username");
2757
            password = (String) sess.getAttribute("password");
2758
            groupnames = (String[]) sess.getAttribute("groupnames");
2759
            try {
2760
                sess_id = (String) sess.getId();
2761
            } catch (IllegalStateException ise) {
2762
                System.out
2763
                        .println("error in  handleMultipartForm: this shouldn't "
2764
                                + "happen: the session should be valid: "
2765
                                + ise.getMessage());
2766
            }
2767
        }
2768

    
2769
        // Get the out stream
2770
        try {
2771
            out = response.getWriter();
2772
        } catch (IOException ioe2) {
2773
            logMetacat.error("Fatal Error: couldn't get response "
2774
                    + "output stream.");
2775
        }
2776

    
2777
        if (action.equals("upload")) {
2778
            if (username != null && !username.equals("public")) {
2779
                handleUploadAction(request, out, params, fileList, username,
2780
                        groupnames);
2781
            } else {
2782

    
2783
                out.println("<?xml version=\"1.0\"?>");
2784
                out.println("<error>");
2785
                out.println("Permission denied for " + action);
2786
                out.println("</error>");
2787
            }
2788
        } else {
2789
            /*
2790
             * try { out = response.getWriter(); } catch (IOException ioe2) {
2791
             * System.err.println("Fatal Error: couldn't get response output
2792
             * stream.");
2793
             */
2794
            out.println("<?xml version=\"1.0\"?>");
2795
            out.println("<error>");
2796
            out.println(
2797
                    "Error: action not registered.  Please report this error.");
2798
            out.println("</error>");
2799
        }
2800
        out.close();
2801
    }
2802

    
2803
    /**
2804
     * Handle the upload action by saving the attached file to disk and
2805
     * registering it in the Metacat db
2806
     */
2807
    private void handleUploadAction(HttpServletRequest request,
2808
            PrintWriter out, Hashtable params, Hashtable fileList,
2809
            String username, String[] groupnames)
2810
    {
2811
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2812
        //PrintWriter out = null;
2813
        //Connection conn = null;
2814
        String action = null;
2815
        String docid = null;
2816

    
2817
        /*
2818
         * response.setContentType("text/xml"); try { out =
2819
         * response.getWriter(); } catch (IOException ioe2) {
2820
         * System.err.println("Fatal Error: couldn't get response output
2821
         * stream.");
2822
         */
2823

    
2824
        if (params.containsKey("docid")) {
2825
            docid = (String) params.get("docid");
2826
        }
2827

    
2828
        // Make sure we have a docid and datafile
2829
        if (docid != null && fileList.containsKey("datafile")) {
2830
            logMetacat.info("Uploading data docid: " + docid);
2831
            // Get a reference to the file part of the form
2832
            FilePart filePart = (FilePart) fileList.get("datafile");
2833
            String fileName = filePart.getFileName();
2834
            logMetacat.info("Uploading filename: " + fileName);
2835
            // Check if the right file existed in the uploaded data
2836
            if (fileName != null) {
2837

    
2838
                try {
2839
                    //logMetacat.info("Upload datafile " + docid
2840
                    // +"...", 10);
2841
                    //If document get lock data file grant
2842
                    if (DocumentImpl.getDataFileLockGrant(docid)) {
2843
                        // Save the data file to disk using "docid" as the name
2844
                        String datafilepath = MetaCatUtil.getOption("datafilepath");
2845
                        File dataDirectory = new File(datafilepath);
2846
                        dataDirectory.mkdirs();
2847
                        File newFile = null;
2848
                        long size = 0;
2849
                        try
2850
                        {
2851
                          newFile = new File(dataDirectory, docid);
2852
                          size = filePart.writeTo(newFile);
2853
                        
2854
//                        register the file in the database (which generates
2855
                          // an exception
2856
                          //if the docid is not acceptable or other untoward
2857
                          // things happen
2858
                          DocumentImpl.registerDocument(fileName, "BIN", docid,
2859
                                username, groupnames);
2860
                        }
2861
                        catch (Exception ee)
2862
                        {
2863
                           //detelte the file to create
2864
                            newFile.delete();
2865
                            throw ee;
2866
                        }
2867

    
2868
                        EventLog.getInstance().log(request.getRemoteAddr(),
2869
                                username, docid, "upload");
2870
                        // Force replication this data file
2871
                        // To data file, "insert" and update is same
2872
                        // The fourth parameter is null. Because it is
2873
                        // notification server
2874
                        // and this method is in MetaCatServerlet. It is
2875
                        // original command,
2876
                        // not get force replication info from another metacat
2877
                        ForceReplicationHandler frh = new ForceReplicationHandler(
2878
                                docid, "insert", false, null);
2879

    
2880
                        // set content type and other response header fields
2881
                        // first
2882
                        out.println("<?xml version=\"1.0\"?>");
2883
                        out.println("<success>");
2884
                        out.println("<docid>" + docid + "</docid>");
2885
                        out.println("<size>" + size + "</size>");
2886
                        out.println("</success>");
2887
                    }
2888

    
2889
                } catch (Exception e) {
2890
                    
2891
                    out.println("<?xml version=\"1.0\"?>");
2892
                    out.println("<error>");
2893
                    out.println(e.getMessage());
2894
                    out.println("</error>");
2895
                }
2896
            } else {
2897
                // the field did not contain a file
2898
                out.println("<?xml version=\"1.0\"?>");
2899
                out.println("<error>");
2900
                out.println("The uploaded data did not contain a valid file.");
2901
                out.println("</error>");
2902
            }
2903
        } else {
2904
            // Error bcse docid missing or file missing
2905
            out.println("<?xml version=\"1.0\"?>");
2906
            out.println("<error>");
2907
            out.println("The uploaded data did not contain a valid docid "
2908
                    + "or valid file.");
2909
            out.println("</error>");
2910
        }
2911
    }
2912

    
2913
    /*
2914
     * A method to handle set access action
2915
     */
2916
    private void handleSetAccessAction(PrintWriter out, Hashtable params,
2917
            String username)
2918
    {
2919
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2920
        String[] docList = null;
2921
        String[] principalList = null;
2922
        String[] permissionList = null;
2923
        String[] permTypeList = null;
2924
        String[] permOrderList = null;
2925
        String permission = null;
2926
        String permType = null;
2927
        String permOrder = null;
2928
        Vector errorList = new Vector();
2929
        String error = null;
2930
        Vector successList = new Vector();
2931
        String success = null;
2932

    
2933
        // Get parameters
2934
        if (params.containsKey("docid")) {
2935
            docList = (String[]) params.get("docid");
2936
        }
2937
        if (params.containsKey("principal")) {
2938
            principalList = (String[]) params.get("principal");
2939
        }
2940
        if (params.containsKey("permission")) {
2941
            permissionList = (String[]) params.get("permission");
2942

    
2943
        }
2944
        if (params.containsKey("permType")) {
2945
            permTypeList = (String[]) params.get("permType");
2946

    
2947
        }
2948
        if (params.containsKey("permOrder")) {
2949
            permOrderList = (String[]) params.get("permOrder");
2950

    
2951
        }
2952

    
2953
        // Make sure the parameter is not null
2954
        if (docList == null || principalList == null || permTypeList == null
2955
                || permissionList == null) {
2956
            error = "Please check your parameter list, it should look like: "
2957
                    + "?action=setaccess&docid=pipeline.1.1&principal=public"
2958
                    + "&permission=read&permType=allow&permOrder=allowFirst";
2959
            errorList.addElement(error);
2960
            outputResponse(successList, errorList, out);
2961
            return;
2962
        }
2963

    
2964
        // Only select first element for permission, type and order
2965
        permission = permissionList[0];
2966
        permType = permTypeList[0];
2967
        if (permOrderList != null) {
2968
            permOrder = permOrderList[0];
2969
        }
2970

    
2971
        // Get package doctype set
2972
        Vector packageSet = MetaCatUtil.getOptionList(MetaCatUtil
2973
                .getOption("packagedoctypeset"));
2974
        //debug
2975
        if (packageSet != null) {
2976
            for (int i = 0; i < packageSet.size(); i++) {
2977
                logMetacat.debug("doctype in package set: "
2978
                        + (String) packageSet.elementAt(i));
2979
            }
2980
        }
2981

    
2982
        // handle every accessionNumber
2983
        for (int i = 0; i < docList.length; i++) {
2984
            String accessionNumber = docList[i];
2985
            String owner = null;
2986
            String publicId = null;
2987
            // Get document owner and public id
2988
            try {
2989
                owner = getFieldValueForDoc(accessionNumber, "user_owner");
2990
                publicId = getFieldValueForDoc(accessionNumber, "doctype");
2991
            } catch (Exception e) {
2992
                logMetacat.error("Error in handleSetAccessAction: "
2993
                        + e.getMessage());
2994
                error = "Error in set access control for document - "
2995
                        + accessionNumber + e.getMessage();
2996
                errorList.addElement(error);
2997
                continue;
2998
            }
2999
            //check if user is the owner. Only owner can do owner
3000
            if (username == null || owner == null || !username.equals(owner)) {
3001
                error = "User - " + username
3002
                        + " does not have permission to set "
3003
                        + "access control for docid - " + accessionNumber;
3004
                errorList.addElement(error);
3005
                continue;
3006
            }
3007

    
3008
            // If docid publicid is BIN data file or other beta4, 6 package
3009
            // document
3010
            // we could not do set access control. Because we don't want
3011
            // inconsistent
3012
            // to its access docuemnt
3013
            if (publicId != null && packageSet != null
3014
                    && packageSet.contains(publicId)) {
3015
                error = "Could not set access control to document "
3016
                        + accessionNumber
3017
                        + "because it is in a pakcage and it has a access file for it";
3018
                errorList.addElement(error);
3019
                continue;
3020
            }
3021

    
3022
            // for every principle
3023
            for (int j = 0; j < principalList.length; j++) {
3024
                String principal = principalList[j];
3025
                try {
3026
                    //insert permission
3027
                    AccessControlForSingleFile accessControl = new AccessControlForSingleFile(
3028
                            accessionNumber, principal, permission, permType,
3029
                            permOrder);
3030
                    accessControl.insertPermissions();
3031
                    success = "Set access control to document "
3032
                            + accessionNumber + " successfully";
3033
                    successList.addElement(success);
3034
                } catch (Exception ee) {
3035
                    logMetacat.error(
3036
                            "Erorr in handleSetAccessAction2: "
3037
                                    + ee.getMessage());
3038
                    error = "Faild to set access control for document "
3039
                            + accessionNumber + " because " + ee.getMessage();
3040
                    errorList.addElement(error);
3041
                    continue;
3042
                }
3043
            }
3044
        }
3045
        outputResponse(successList, errorList, out);
3046
    }
3047

    
3048
    /*
3049
     * A method try to determin a docid's public id, if couldn't find null will
3050
     * be returned.
3051
     */
3052
    private String getFieldValueForDoc(String accessionNumber, String fieldName)
3053
            throws Exception
3054
    {
3055
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
3056
        if (accessionNumber == null || accessionNumber.equals("")
3057
                || fieldName == null || fieldName.equals("")) { throw new Exception(
3058
                "Docid or field name was not specified"); }
3059

    
3060
        PreparedStatement pstmt = null;
3061
        ResultSet rs = null;
3062
        String fieldValue = null;
3063
        String docId = null;
3064
        DBConnection conn = null;
3065
        int serialNumber = -1;
3066

    
3067
        // get rid of revision if access number has
3068
        docId = MetaCatUtil.getDocIdFromString(accessionNumber);
3069
        try {
3070
            //check out DBConnection
3071
            conn = DBConnectionPool
3072
                    .getDBConnection("MetaCatServlet.getPublicIdForDoc");
3073
            serialNumber = conn.getCheckOutSerialNumber();
3074
            pstmt = conn.prepareStatement("SELECT " + fieldName
3075
                    + " FROM xml_documents " + "WHERE docid = ? ");
3076

    
3077
            pstmt.setString(1, docId);
3078
            pstmt.execute();
3079
            rs = pstmt.getResultSet();
3080
            boolean hasRow = rs.next();
3081
            int perm = 0;
3082
            if (hasRow) {
3083
                fieldValue = rs.getString(1);
3084
            } else {
3085
                throw new Exception("Could not find document: "
3086
                        + accessionNumber);
3087
            }
3088
        } catch (Exception e) {
3089
            logMetacat.error(
3090
                    "Exception in MetacatServlet.getPublicIdForDoc: "
3091
                            + e.getMessage());
3092
            throw e;
3093
        } finally {
3094
            try {
3095
                rs.close();
3096
                pstmt.close();
3097

    
3098
            } finally {
3099
                DBConnectionPool.returnDBConnection(conn, serialNumber);
3100
            }
3101
        }
3102
        return fieldValue;
3103
    }
3104

    
3105
    /*
3106
     * Get the list of documents from the database and return the list in an
3107
     * Vector of identifiers.
3108
     *
3109
     * @ returns the array of identifiers
3110
     */
3111
    private Vector getDocumentList() throws SQLException
3112
    {
3113
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
3114
        Vector docList = new Vector();
3115
        PreparedStatement pstmt = null;
3116
        ResultSet rs = null;
3117
        DBConnection conn = null;
3118
        int serialNumber = -1;
3119

    
3120
        try {
3121
            //check out DBConnection
3122
            conn = DBConnectionPool
3123
                    .getDBConnection("MetaCatServlet.getDocumentList");
3124
            serialNumber = conn.getCheckOutSerialNumber();
3125
            pstmt = conn.prepareStatement("SELECT docid, rev"
3126
                    + " FROM xml_documents ");
3127
            pstmt.execute();
3128
            rs = pstmt.getResultSet();
3129
            while (rs.next()) {
3130
                String docid = rs.getString(1);
3131
                String rev = rs.getString(2);
3132
                docList.add(docid + "." + rev);
3133
            }
3134
        } catch (SQLException e) {
3135
            logMetacat.error(
3136
                    "Exception in MetacatServlet.getDocumentList: "
3137
                            + e.getMessage());
3138
            throw e;
3139
        } finally {
3140
            try {
3141
                rs.close();
3142
                pstmt.close();
3143

    
3144
            } catch (SQLException se) {
3145
                logMetacat.error(
3146
                    "Exception in MetacatServlet.getDocumentList: "
3147
                            + se.getMessage());
3148
                throw se;
3149
            } finally {
3150
                DBConnectionPool.returnDBConnection(conn, serialNumber);
3151
            }
3152
        }
3153
        return docList;
3154
    }
3155

    
3156
    /*
3157
     * A method to output setAccess action result
3158
     */
3159
    private void outputResponse(Vector successList, Vector errorList,
3160
            PrintWriter out)
3161
    {
3162
        boolean error = false;
3163
        boolean success = false;
3164
        // Output prolog
3165
        out.println(PROLOG);
3166
        // output success message
3167
        if (successList != null) {
3168
            for (int i = 0; i < successList.size(); i++) {
3169
                out.println(SUCCESS);
3170
                out.println((String) successList.elementAt(i));
3171
                out.println(SUCCESSCLOSE);
3172
                success = true;
3173
            }
3174
        }
3175
        // output error message
3176
        if (errorList != null) {
3177
            for (int i = 0; i < errorList.size(); i++) {
3178
                out.println(ERROR);
3179
                out.println((String) errorList.elementAt(i));
3180
                out.println(ERRORCLOSE);
3181
                error = true;
3182
            }
3183
        }
3184

    
3185
        // if no error and no success info, send a error that nothing happened
3186
        if (!error && !success) {
3187
            out.println(ERROR);
3188
            out.println("Nothing happend for setaccess action");
3189
            out.println(ERRORCLOSE);
3190
        }
3191
    }
3192
    
3193
    /**
3194
     * Method to get session table which store the session info
3195
     * @return
3196
     */
3197
    public static Hashtable getSessionHash()
3198
    {
3199
        return sessionHash;
3200
    }
3201
    
3202
    /*
3203
     * If the given docid only have one seperter, we need 
3204
     * append rev for it. The rev come from xml_documents
3205
     */
3206
    private static String appendRev(String docid) throws Exception
3207
    {
3208
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
3209
        String newAccNum = null;
3210
        String separator = MetaCatUtil.getOption("accNumSeparator");
3211
        int firstIndex = docid.indexOf(separator);
3212
        int lastIndex = docid.lastIndexOf(separator);
3213
        if (firstIndex == lastIndex)
3214
        {
3215
            
3216
           //only one seperater
3217
            int rev = DBUtil.getLatestRevisionInDocumentTable(docid);
3218
            if (rev == -1)
3219
            {
3220
                throw new Exception("the requested docid '"
3221
                        + docid+ "' does not exist");
3222
            }
3223
            else
3224
            {
3225
                newAccNum = docid+ separator+ rev;
3226
            }
3227
        }
3228
        else
3229
        {
3230
            // in other suituation we don't change the docid
3231
            newAccNum = docid;
3232
        }
3233
        //logMetacat.debug("The docid will be read is "+newAccNum);
3234
        return newAccNum;
3235
  }
3236
}
(44-44/65)