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

    
27
package edu.ucsb.nceas.metacat;
28

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

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

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

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

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

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

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

    
153
            String LOG_CONFIG_NAME = dirPath + "/log4j.properties";
154
            PropertyConfigurator.configureAndWatch(LOG_CONFIG_NAME);
155
            
156
            Options options = null;
157
            try {
158
                options = Options.initialize(propertyFile);
159
                logMetacat.info("Options configured: "
160
                    + options.getOption("configured"));
161
            } catch (IOException ioe) {
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
                    logMetacat.error("Error in loading options for skin " + "skinName" +" : "
202
                            + ioe.getMessage());
203
                }                
204
                MetaCatUtil.skinconfigs.put(skinName, skinOption);
205
            }
206

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

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

    
223
		// After running the first time, we want to to set regenerateCacheOnRestart to false
224
		// so that it does not regenerate the cache every time tomcat is restarted
225
		MetaCatUtil.setOption("regenerateCacheOnRestart","false");
226

    
227
                // End timer
228
                long after = System.currentTimeMillis();
229
                logMetacat.info(" ------ Spatial Harvester Time  " + (after - before) + "ms");
230

    
231
	    } else {
232
                logMetacat.info(" \n **** Spatial cache is not set to regenerate on restart");
233
            }
234
           
235
           
236
            logMetacat.info("Metacat (" + Version.getVersion()
237
                               + ") initialized.");
238

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

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

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

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

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

    
274
        // Process the data and send back the response
275
        handleGetOrPost(request, response);
276
    }
277

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

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

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

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

    
450
            String name = null;
451
            String[] value = null;
452
            String[] docid = new String[3];
453
            Hashtable params = new Hashtable();
454
            Enumeration paramlist = request.getParameterNames();
455

    
456
            while (paramlist.hasMoreElements()) {
457

    
458
                name = (String) paramlist.nextElement();
459
                value = request.getParameterValues(name);
460

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

    
471
                params.put(name, value);
472
            }
473

    
474
            //handle param is emptpy
475
            if (params.isEmpty() || params == null) { return; }
476

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

    
490
            String action = ((String[]) params.get("action"))[0];
491
            logMetacat.info("Action is: " + action);
492

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

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

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

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

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

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

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

    
774
            //util.closeConnections();
775
            // Close the stream to the client
776
            //out.close();
777
        }
778
    }
779

    
780
    /////////////////////////////// METACAT SPATIAL ///////////////////////////
781

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

    
796
	if ( !MetaCatUtil.getOption("runSpatialOption").equals("true") ) {
797
        	response.setContentType("text/html");
798
        	out.println("<html> Metacat Spatial Option is turned off </html>");
799
        	out.close();
800
		return ;
801
	}		
802
      
803
        /* 
804
         * Perform spatial query against spatial cache
805
         */
806
        float _xmax = Float.valueOf( ((String[]) params.get("xmax"))[0] ).floatValue();
807
        float _ymax = Float.valueOf( ((String[]) params.get("ymax"))[0] ).floatValue();
808
        float _xmin = Float.valueOf( ((String[]) params.get("xmin"))[0] ).floatValue();
809
        float _ymin = Float.valueOf( ((String[]) params.get("ymin"))[0] ).floatValue();
810
        SpatialQuery sq = new SpatialQuery();
811
        Vector docids = sq.filterByBbox( _xmin, _ymin, _xmax, _ymax );
812
        // logMetacat.info(" --- Spatial Query completed. Passing on the SQuery handler");
813
        // logMetacat.warn("\n\n ******* after spatial query, we've got " + docids.size() + " docids \n\n");
814

    
815
        /*
816
         * Create an array matching docids
817
         */
818
        String [] docidArray = new String[docids.size()];
819
        docids.toArray(docidArray);
820

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

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

    
844
        // change the action
845
        String[] actionArray = new String[1];
846
        actionArray[0] = "squery";
847
        params.put("action", actionArray);
848

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

    
857
        DBQuery queryobj = new DBQuery(docids);
858
        queryobj.findDocuments(response, out, params, username, groupnames, sess_id);
859

    
860
  }
861

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

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

    
882
        //}
883

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

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

    
897
        String qformat = "xml";
898
        if(params.get("qformat") != null){
899
            qformat = ((String[]) params.get("qformat"))[0];
900
        }
901

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

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

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

    
935
                logMetacat.error(
936
                        "Error in MetaCatServlet.handleLoginAction: "
937
                                + e.getMessage());
938
            }
939
        }
940
    }
941

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

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

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

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

    
992
    // END OF LOGIN & LOGOUT SECTION
993

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

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

    
1042
        //handleSQuery(out, params, response,user, groups, sessionid);
1043
    }
1044

    
1045
    // END OF SQUERY & QUERY SECTION
1046

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

    
1067
        String[] docs = new String[10];
1068
        String docId = "";
1069

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

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

    
1131
            logMetacat.error(
1132
                    "Error in MetacatServlet.handleExportAction: "
1133
                            + e.getMessage());
1134
            e.printStackTrace(System.out);
1135

    
1136
        }
1137

    
1138
    }
1139

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

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

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

    
1198
                }//if
1199
              }//try
1200
              catch (Exception e)
1201
              {
1202
                throw e;
1203
              }//catch
1204
            }//else
1205

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

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

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

    
1270
        try {
1271
            //check out DBConnection
1272
            conn = DBConnectionPool
1273
                    .getDBConnection("AccessControlList.isAllowFirst");
1274
            serialNumber = conn.getCheckOutSerialNumber();
1275

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

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

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

    
1326
        try {
1327
            String[] docs = new String[0];
1328
            String docid = "";
1329
            String qformat = "";
1330
            String abstrpath = null;
1331

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

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

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

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

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

    
1396
            if (zip) {
1397
                zout.finish(); //terminate the zip file
1398
                zout.close(); //close the zip stream
1399
            }
1400

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

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

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

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

    
1484
                }
1485
                // Close zip output stream
1486
                if (zout != null) {
1487
                    zout.close();
1488
                }
1489

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

    
1496
            }
1497

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

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

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

    
1533
                throw e;
1534
            }
1535

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

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

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

    
1561
                // Set the name of the data file to the entity name plus docid, 
1562
                // or if that is unavailable, use the docid alone
1563
                String docname = doc.getDocname();
1564
                if (docname == null || docname.equals("")) {
1565
                    docname = docid;
1566
                } else {
1567
                    docname = docid + "-" + docname;
1568
                }
1569
                response.setHeader("Content-Disposition", 
1570
                        "attachment; filename=" + docname);
1571
                
1572
                try {
1573
                    ServletOutputStream out = response.getOutputStream();
1574
                    byte[] buf = new byte[4 * 1024]; // 4K buffer
1575
                    int b = fin.read(buf);
1576
                    while (b != -1) {
1577
                        out.write(buf, 0, b);
1578
                        b = fin.read(buf);
1579
                    }
1580
                } finally {
1581
                    if (fin != null) fin.close();
1582
                }
1583

    
1584
            } else {
1585
                // this is metadata doc
1586
                if (qformat.equals("xml") || qformat.equals("")) {
1587
                    // if equals "", that means no qformat is specified. hence
1588
                    // by default the document should be returned in xml format
1589
                    // set content type first
1590
                    response.setContentType("text/xml"); //MIME type
1591
                    response.setHeader("Content-Disposition", 
1592
                            "attachment; filename=" + docid + ".xml");
1593
                    PrintWriter out = response.getWriter();
1594
                    doc.toXml(out, user, groups, withInlineData);
1595
                } else {
1596
                    response.setContentType("text/html"); //MIME type
1597
                    PrintWriter out = response.getWriter();
1598

    
1599
                    // Look up the document type
1600
                    String doctype = doc.getDoctype();
1601
                    // Transform the document to the new doctype
1602
                    DBTransform dbt = new DBTransform();
1603
                    dbt.transformXMLDocument(doc.toString(user, groups,
1604
                            withInlineData), doctype, "-//W3C//HTML//EN",
1605
                            qformat, out, params);
1606
                }
1607

    
1608
            }
1609
            EventLog.getInstance().log(request.getRemoteAddr(), user,
1610
                    docid, "read");
1611
        } catch (Exception except) {
1612
            throw except;
1613
        }
1614
    }
1615

    
1616
    /**
1617
     * read data from URLConnection
1618
     */
1619
    private void readFromURLConnection(HttpServletResponse response,
1620
            String docid) throws IOException, MalformedURLException
1621
    {
1622
        ServletOutputStream out = response.getOutputStream();
1623
        String contentType = getServletContext().getMimeType(docid); //MIME
1624
                                                                     // type
1625
        if (contentType == null) {
1626
            if (docid.endsWith(".xml")) {
1627
                contentType = "text/xml";
1628
            } else if (docid.endsWith(".css")) {
1629
                contentType = "text/css";
1630
            } else if (docid.endsWith(".dtd")) {
1631
                contentType = "text/plain";
1632
            } else if (docid.endsWith(".xsd")) {
1633
                contentType = "text/xml";
1634
            } else if (docid.endsWith("/")) {
1635
                contentType = "text/html";
1636
            } else {
1637
                File f = new File(docid);
1638
                if (f.isDirectory()) {
1639
                    contentType = "text/html";
1640
                } else {
1641
                    contentType = "application/octet-stream";
1642
                }
1643
            }
1644
        }
1645
        response.setContentType(contentType);
1646
        // if we decide to use "application/octet-stream" for all data returns
1647
        // response.setContentType("application/octet-stream");
1648

    
1649
        // this is http url
1650
        URL url = new URL(docid);
1651
        BufferedInputStream bis = null;
1652
        try {
1653
            bis = new BufferedInputStream(url.openStream());
1654
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1655
            int b = bis.read(buf);
1656
            while (b != -1) {
1657
                out.write(buf, 0, b);
1658
                b = bis.read(buf);
1659
            }
1660
        } finally {
1661
            if (bis != null) bis.close();
1662
        }
1663

    
1664
    }
1665

    
1666
    /**
1667
     * read file/doc and write to ZipOutputStream
1668
     *
1669
     * @param docid
1670
     * @param zout
1671
     * @param user
1672
     * @param groups
1673
     * @throws ClassNotFoundException
1674
     * @throws IOException
1675
     * @throws SQLException
1676
     * @throws McdbException
1677
     * @throws Exception
1678
     */
1679
    private void addDocToZip(HttpServletRequest request, String docid,
1680
            ZipOutputStream zout, String user, String[] groups) throws
1681
            ClassNotFoundException, IOException, SQLException, McdbException,
1682
            Exception
1683
    {
1684
        byte[] bytestring = null;
1685
        ZipEntry zentry = null;
1686

    
1687
        try {
1688
            URL url = new URL(docid);
1689

    
1690
            // this http url; read from URLConnection; add to zip
1691
            zentry = new ZipEntry(docid);
1692
            zout.putNextEntry(zentry);
1693
            BufferedInputStream bis = null;
1694
            try {
1695
                bis = new BufferedInputStream(url.openStream());
1696
                byte[] buf = new byte[4 * 1024]; // 4K buffer
1697
                int b = bis.read(buf);
1698
                while (b != -1) {
1699
                    zout.write(buf, 0, b);
1700
                    b = bis.read(buf);
1701
                }
1702
            } finally {
1703
                if (bis != null) bis.close();
1704
            }
1705
            zout.closeEntry();
1706

    
1707
        } catch (MalformedURLException mue) {
1708

    
1709
            // this is metacat doc (data file or metadata doc)
1710
            try {
1711
                DocumentImpl doc = new DocumentImpl(docid);
1712

    
1713
                //check the permission for read
1714
                if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1715
                    Exception e = new Exception("User " + user
1716
                            + " does not have "
1717
                            + "permission to read the document with the docid "
1718
                            + docid);
1719
                    throw e;
1720
                }
1721

    
1722
                if (doc.getRootNodeID() == 0) {
1723
                    // this is data file; add file to zip
1724
                    String filepath = MetaCatUtil.getOption("datafilepath");
1725
                    if (!filepath.endsWith("/")) {
1726
                        filepath += "/";
1727
                    }
1728
                    String filename = filepath + docid;
1729
                    FileInputStream fin = null;
1730
                    fin = new FileInputStream(filename);
1731
                    try {
1732

    
1733
                        zentry = new ZipEntry(docid);
1734
                        zout.putNextEntry(zentry);
1735
                        byte[] buf = new byte[4 * 1024]; // 4K buffer
1736
                        int b = fin.read(buf);
1737
                        while (b != -1) {
1738
                            zout.write(buf, 0, b);
1739
                            b = fin.read(buf);
1740
                        }
1741
                    } finally {
1742
                        if (fin != null) fin.close();
1743
                    }
1744
                    zout.closeEntry();
1745

    
1746
                } else {
1747
                    // this is metadata doc; add doc to zip
1748
                    bytestring = doc.toString().getBytes();
1749
                    zentry = new ZipEntry(docid + ".xml");
1750
                    zentry.setSize(bytestring.length);
1751
                    zout.putNextEntry(zentry);
1752
                    zout.write(bytestring, 0, bytestring.length);
1753
                    zout.closeEntry();
1754
                }
1755
                EventLog.getInstance().log(request.getRemoteAddr(), user,
1756
                        docid, "read");
1757
            } catch (Exception except) {
1758
                throw except;
1759
            }
1760
        }
1761
    }
1762

    
1763
    /**
1764
     * If metacat couldn't find a data file or document locally, it will read
1765
     * this docid from its home server. This is for the replication feature
1766
     */
1767
    private void readFromRemoteMetaCat(HttpServletResponse response,
1768
            String docid, String rev, String user, String password,
1769
            ServletOutputStream out, boolean zip, ZipOutputStream zout)
1770
            throws Exception
1771
    {
1772
        // Create a object of RemoteDocument, "" is for zipEntryPath
1773
        RemoteDocument remoteDoc = new RemoteDocument(docid, rev, user,
1774
                password, "");
1775
        String docType = remoteDoc.getDocType();
1776
        // Only read data file
1777
        if (docType.equals("BIN")) {
1778
            // If it is zip format
1779
            if (zip) {
1780
                remoteDoc.readDocumentFromRemoteServerByZip(zout);
1781
            } else {
1782
                if (out == null) {
1783
                    out = response.getOutputStream();
1784
                }
1785
                response.setContentType("application/octet-stream");
1786
                remoteDoc.readDocumentFromRemoteServer(out);
1787
            }
1788
        } else {
1789
            throw new Exception("Docid: " + docid + "." + rev
1790
                    + " couldn't find");
1791
        }
1792
    }
1793

    
1794
    /**
1795
     * Handle the database putdocument request and write an XML document to the
1796
     * database connection
1797
     */
1798
    private void handleInsertOrUpdateAction(HttpServletRequest request,
1799
            HttpServletResponse response, PrintWriter out, Hashtable params,
1800
            String user, String[] groups)
1801
    {
1802
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1803
        DBConnection dbConn = null;
1804
        int serialNumber = -1;
1805

    
1806
        if(params.get("docid") == null){
1807
            out.println("<?xml version=\"1.0\"?>");
1808
            out.println("<error>");
1809
            out.println("Docid not specified");
1810
            out.println("</error>");
1811
            logMetacat.error("Docid not specified");
1812
            return;
1813
        }
1814
        
1815
        if(!MetaCatUtil.canInsertOrUpdate(user, groups)){
1816
        	out.println("<?xml version=\"1.0\"?>");
1817
            out.println("<error>");
1818
            out.println("User '" + user + "' not allowed to insert and update");
1819
            out.println("</error>");
1820
            logMetacat.error("User '" + user + "' not allowed to insert and update");
1821
            return;
1822
        }
1823

    
1824
        try {
1825
            // Get the document indicated
1826
            String[] doctext = (String[]) params.get("doctext");
1827
            String pub = null;
1828
            if (params.containsKey("public")) {
1829
                pub = ((String[]) params.get("public"))[0];
1830
            }
1831

    
1832
            StringReader dtd = null;
1833
            if (params.containsKey("dtdtext")) {
1834
                String[] dtdtext = (String[]) params.get("dtdtext");
1835
                try {
1836
                    if (!dtdtext[0].equals("")) {
1837
                        dtd = new StringReader(dtdtext[0]);
1838
                    }
1839
                } catch (NullPointerException npe) {
1840
                }
1841
            }
1842

    
1843
            if(doctext == null){
1844
                out.println("<?xml version=\"1.0\"?>");
1845
                out.println("<error>");
1846
                out.println("Document text not submitted");
1847
                out.println("</error>");
1848
                return;
1849
            }
1850

    
1851
            StringReader xml = new StringReader(doctext[0]);
1852
            boolean validate = false;
1853
            DocumentImplWrapper documentWrapper = null;
1854
            try {
1855
                // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ...
1856
                // >
1857
                // in order to decide whether to use validation parser
1858
                validate = needDTDValidation(xml);
1859
                if (validate) {
1860
                    // set a dtd base validation parser
1861
                    String rule = DocumentImpl.DTD;
1862
                    documentWrapper = new DocumentImplWrapper(rule, validate);
1863
                } else {
1864

    
1865
                    String namespace = findNamespace(xml);
1866
                    
1867
                	if (namespace != null) {
1868
                		if (namespace.compareTo(DocumentImpl.EML2_0_0NAMESPACE) == 0
1869
                				|| namespace.compareTo(
1870
                				DocumentImpl.EML2_0_1NAMESPACE) == 0) {
1871
                			// set eml2 base	 validation parser
1872
                			String rule = DocumentImpl.EML200;
1873
                			// using emlparser to check id validation
1874
                			EMLParser parser = new EMLParser(doctext[0]);
1875
                			documentWrapper = new DocumentImplWrapper(rule, true);
1876
                		} else if (namespace.compareTo(
1877
                                DocumentImpl.EML2_1_0NAMESPACE) == 0) {
1878
                			// set eml2 base validation parser
1879
                			String rule = DocumentImpl.EML210;
1880
                			// using emlparser to check id validation
1881
                			EMLParser parser = new EMLParser(doctext[0]);
1882
                			documentWrapper = new DocumentImplWrapper(rule, true);
1883
                		} else {
1884
                			// set schema base validation parser
1885
                			String rule = DocumentImpl.SCHEMA;
1886
                			documentWrapper = new DocumentImplWrapper(rule, true);
1887
                		}
1888
                	} else {
1889
                		documentWrapper = new DocumentImplWrapper("", false);
1890
                	}
1891
                }
1892

    
1893
                String[] action = (String[]) params.get("action");
1894
                String[] docid = (String[]) params.get("docid");
1895
                String newdocid = null;
1896

    
1897
                String doAction = null;
1898
                if (action[0].equals("insert")) {
1899
                    doAction = "INSERT";
1900
                } else if (action[0].equals("update")) {
1901
                    doAction = "UPDATE";
1902
                }
1903

    
1904
                try {
1905
                    // get a connection from the pool
1906
                    dbConn = DBConnectionPool
1907
                            .getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1908
                    serialNumber = dbConn.getCheckOutSerialNumber();
1909

    
1910
                    // write the document to the database
1911
                    try {
1912
                        String accNumber = docid[0];
1913
                        logMetacat.debug("" + doAction + " "
1914
                                + accNumber + "...");
1915
                        if (accNumber.equals("")) {
1916
                            accNumber = null;
1917
                        }
1918
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1919
                                doAction, accNumber, user, groups);
1920
                        EventLog.getInstance().log(request.getRemoteAddr(),
1921
                                user, accNumber, action[0]);
1922
                    } catch (NullPointerException npe) {
1923
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1924
                                doAction, null, user, groups);
1925
                        EventLog.getInstance().log(request.getRemoteAddr(),
1926
                                user, "", action[0]);
1927
                    }
1928
                }
1929
                finally {
1930
                    // Return db connection
1931
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1932
                }
1933

    
1934
                // set content type and other response header fields first
1935
                //response.setContentType("text/xml");
1936
                out.println("<?xml version=\"1.0\"?>");
1937
                out.println("<success>");
1938
                out.println("<docid>" + newdocid + "</docid>");
1939
                out.println("</success>");
1940

    
1941
            } catch (NullPointerException npe) {
1942
                //response.setContentType("text/xml");
1943
                out.println("<?xml version=\"1.0\"?>");
1944
                out.println("<error>");
1945
                out.println(npe.getMessage());
1946
                out.println("</error>");
1947
                logMetacat.warn("Error in writing eml document to the database" + npe.getMessage());
1948
                npe.printStackTrace();
1949
            }
1950
        } catch (Exception e) {
1951
            //response.setContentType("text/xml");
1952
            out.println("<?xml version=\"1.0\"?>");
1953
            out.println("<error>");
1954
            out.println(e.getMessage());
1955
            out.println("</error>");
1956
            logMetacat.warn("Error in writing eml document to the database" + e.getMessage());
1957
            e.printStackTrace();
1958
        }
1959
    }
1960

    
1961
    /**
1962
     * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > in
1963
     * order to decide whether to use validation parser
1964
     */
1965
    private static boolean needDTDValidation(StringReader xmlreader)
1966
            throws IOException
1967
    {
1968
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1969
        StringBuffer cbuff = new StringBuffer();
1970
        java.util.Stack st = new java.util.Stack();
1971
        boolean validate = false;
1972
        int c;
1973
        int inx;
1974

    
1975
        // read from the stream until find the keywords
1976
        while ((st.empty() || st.size() < 4) && ((c = xmlreader.read()) != -1)) {
1977
            cbuff.append((char) c);
1978

    
1979
            // "<!DOCTYPE" keyword is found; put it in the stack
1980
            if ((inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1) {
1981
                cbuff = new StringBuffer();
1982
                st.push("<!DOCTYPE");
1983
            }
1984
            // "PUBLIC" keyword is found; put it in the stack
1985
            if ((inx = cbuff.toString().indexOf("PUBLIC")) != -1) {
1986
                cbuff = new StringBuffer();
1987
                st.push("PUBLIC");
1988
            }
1989
            // "SYSTEM" keyword is found; put it in the stack
1990
            if ((inx = cbuff.toString().indexOf("SYSTEM")) != -1) {
1991
                cbuff = new StringBuffer();
1992
                st.push("SYSTEM");
1993
            }
1994
            // ">" character is found; put it in the stack
1995
            // ">" is found twice: fisrt from <?xml ...?>
1996
            // and second from <!DOCTYPE ... >
1997
            if ((inx = cbuff.toString().indexOf(">")) != -1) {
1998
                cbuff = new StringBuffer();
1999
                st.push(">");
2000
            }
2001
        }
2002

    
2003
        // close the stream
2004
        xmlreader.reset();
2005

    
2006
        // check the stack whether it contains the keywords:
2007
        // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
2008
        if (st.size() == 4) {
2009
            if (((String) st.pop()).equals(">")
2010
                    && (((String) st.peek()).equals("PUBLIC") | ((String) st
2011
                            .pop()).equals("SYSTEM"))
2012
                    && ((String) st.pop()).equals("<!DOCTYPE")) {
2013
                validate = true;
2014
            }
2015
        }
2016

    
2017
        logMetacat.info("Validation for dtd is " + validate);
2018
        return validate;
2019
    }
2020

    
2021
    // END OF INSERT/UPDATE SECTION
2022

    
2023
    /* check if the xml string contains key words to specify schema loocation */
2024
    private String findNamespace(StringReader xml) throws IOException
2025
    {
2026
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2027
        String namespace = null;
2028

    
2029
        String eml2_0_0NameSpace = DocumentImpl.EML2_0_0NAMESPACE;
2030
        String eml2_0_1NameSpace = DocumentImpl.EML2_0_1NAMESPACE;
2031
        String eml2_1_0NameSpace = DocumentImpl.EML2_1_0NAMESPACE;
2032

    
2033
        if (xml == null) {
2034
            logMetacat.debug("Validation for schema is "
2035
                    + namespace);
2036
            return namespace;
2037
        }
2038
        String targetLine = getSchemaLine(xml);
2039
		
2040
        if (targetLine != null) {
2041

    
2042
        	// find if the root element has prefix
2043
        	String prefix = getPrefix(targetLine);
2044
        	logMetacat.info("prefix is:" + prefix);
2045
        	int startIndex = 0;
2046
        	
2047
        	
2048
        	if(prefix != null)
2049
        	{
2050
        		// if prefix found then look for xmlns:prefix
2051
        		// element to find the ns 
2052
        		String namespaceWithPrefix = NAMESPACEKEYWORD 
2053
        					+ ":" + prefix;
2054
        		startIndex = targetLine.indexOf(namespaceWithPrefix);
2055
            	logMetacat.debug("namespaceWithPrefix is:" + namespaceWithPrefix+":");
2056
            	logMetacat.debug("startIndex is:" + startIndex);
2057
        		
2058
        	} else {
2059
        		// if prefix not found then look for xmlns
2060
        		// attribute to find the ns 
2061
        		startIndex = targetLine.indexOf(NAMESPACEKEYWORD);
2062
            	logMetacat.debug("startIndex is:" + startIndex);
2063
        	}
2064
        		
2065
            int start = 1;
2066
            int end = 1;
2067
            String namespaceString = null;
2068
            int count = 0;
2069
            if (startIndex != -1) {
2070
                for (int i = startIndex; i < targetLine.length(); i++) {
2071
                    if (targetLine.charAt(i) == '"') {
2072
                        count++;
2073
                    }
2074
                    if (targetLine.charAt(i) == '"' && count == 1) {
2075
                        start = i;
2076
                    }
2077
                    if (targetLine.charAt(i) == '"' && count == 2) {
2078
                        end = i;
2079
                        break;
2080
                    }
2081
                }
2082
            } 
2083
            // else: xmlns not found. namespace = null will be returned
2084

    
2085
         	logMetacat.debug("targetLine is " + targetLine);
2086
         	logMetacat.debug("start is " + end);
2087
         	logMetacat.debug("end is " + end);
2088
           
2089
            if(start < end){
2090
            	namespaceString = targetLine.substring(start + 1, end);
2091
            	logMetacat.debug("namespaceString is " + namespaceString);
2092
            }
2093
            logMetacat.debug("namespace in xml is: "
2094
                    + namespaceString);
2095
            if(namespaceString != null){
2096
            	if (namespaceString.indexOf(eml2_0_0NameSpace) != -1) {
2097
            		namespace = eml2_0_0NameSpace;
2098
            	} else if (namespaceString.indexOf(eml2_0_1NameSpace) != -1) {
2099
            		namespace = eml2_0_1NameSpace;
2100
            	} else if (namespaceString.indexOf(eml2_1_0NameSpace) != -1) {
2101
            		namespace = eml2_1_0NameSpace;
2102
            	} else {
2103
            		namespace = namespaceString;
2104
            	}
2105
            }
2106
        }
2107

    
2108
        logMetacat.debug("Validation for eml is " + namespace);
2109

    
2110
        return namespace;
2111

    
2112
    }
2113

    
2114
    private String getSchemaLine(StringReader xml) throws IOException
2115
    {
2116
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2117
        // find the line
2118
        String secondLine = null;
2119
        int count = 0;
2120
        int endIndex = 0;
2121
        int startIndex = 0;
2122
        final int TARGETNUM = 1;
2123
        StringBuffer buffer = new StringBuffer();
2124
        boolean comment = false;
2125
        boolean processingInstruction = false;
2126
        char thirdPreviousCharacter = '?';
2127
        char secondPreviousCharacter = '?';
2128
        char previousCharacter = '?';
2129
        char currentCharacter = '?';
2130
        int tmp = xml.read();
2131
        while (tmp != -1) {
2132
            currentCharacter = (char)tmp;
2133
            //in a comment
2134
            if (currentCharacter == '-' && previousCharacter == '-'
2135
                    && secondPreviousCharacter == '!'
2136
                    && thirdPreviousCharacter == '<') {
2137
                comment = true;
2138
            }
2139
            //out of comment
2140
            if (comment && currentCharacter == '>' && previousCharacter == '-'
2141
                    && secondPreviousCharacter == '-') {
2142
                comment = false;
2143
            }
2144

    
2145
            //in a processingInstruction
2146
            if (currentCharacter == '?' && previousCharacter == '<') {
2147
            	processingInstruction = true;
2148
            }
2149
            
2150
            //out of processingInstruction
2151
            if (processingInstruction && currentCharacter == '>' 
2152
            	&& previousCharacter == '?') {
2153
            	processingInstruction = false;
2154
            }
2155
            
2156
            //this is not comment or a processingInstruction
2157
            if (currentCharacter != '!' && previousCharacter == '<' 
2158
            	&& !comment && !processingInstruction) {
2159
                count++;
2160
            }
2161
            
2162
            // get target line
2163
            if (count == TARGETNUM && currentCharacter != '>') {
2164
                buffer.append(currentCharacter);
2165
            }
2166
            if (count == TARGETNUM && currentCharacter == '>') {
2167
                break;
2168
            }
2169
            thirdPreviousCharacter = secondPreviousCharacter;
2170
            secondPreviousCharacter = previousCharacter;
2171
            previousCharacter = currentCharacter;
2172
            tmp = xml.read();
2173
        }
2174
        secondLine = buffer.toString();
2175
        logMetacat.debug("the second line string is: " + secondLine);
2176
        
2177
        xml.reset();
2178
        return secondLine;
2179
    }
2180

    
2181
    private String getPrefix(String schemaLine)
2182
    {
2183
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2184
        String prefix = null;
2185
        
2186
        if(schemaLine.indexOf(" ") > 0){
2187
            String rootElement = "";
2188
            try {
2189
                rootElement = schemaLine.substring(0, schemaLine.indexOf(" "));
2190
            } catch (StringIndexOutOfBoundsException sioobe) {
2191
                rootElement = schemaLine;
2192
            }
2193

    
2194
            logMetacat.debug("rootElement:" + rootElement);
2195
        
2196
            if(rootElement.indexOf(":") > 0){
2197
                prefix = rootElement.substring(rootElement.indexOf(":") + 1,
2198
                    rootElement.length());
2199
            }
2200
            
2201
            if(prefix != null){
2202
                return prefix.trim();
2203
            }
2204
        }
2205
        return null;
2206
    }
2207

    
2208
    /**
2209
     * Handle the database delete request and delete an XML document from the
2210
     * database connection
2211
     */
2212
    private void handleDeleteAction(PrintWriter out, Hashtable params,
2213
            HttpServletRequest request, HttpServletResponse response,
2214
            String user, String[] groups)
2215
    {
2216
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2217
        String[] docid = (String[]) params.get("docid");
2218

    
2219
        if(docid == null){
2220
          response.setContentType("text/xml");
2221
          out.println("<?xml version=\"1.0\"?>");
2222
          out.println("<error>");
2223
          out.println("Docid not specified.");
2224
          out.println("</error>");
2225
          logMetacat.error("Docid not specified for the document to be deleted.");
2226
        } else {
2227

    
2228
            // delete the document from the database
2229
            try {
2230

    
2231
                try {
2232
                    // null means notify server is null
2233
                    DocumentImpl.delete(docid[0], user, groups, null);
2234
                    EventLog.getInstance().log(request.getRemoteAddr(),
2235
                                               user, docid[0], "delete");
2236
                    response.setContentType("text/xml");
2237
                    out.println("<?xml version=\"1.0\"?>");
2238
                    out.println("<success>");
2239
                    out.println("Document deleted.");
2240
                    out.println("</success>");
2241
                    logMetacat.info("Document deleted.");
2242

    
2243
                    // Delete from spatial cache
2244
                    SpatialHarvester sh = new SpatialHarvester();
2245
                    sh.addToDeleteQue( MetaCatUtil.getSmartDocId( docid[0] ) );
2246
                    sh.destroy();
2247

    
2248
                }
2249
                catch (AccessionNumberException ane) {
2250
                    response.setContentType("text/xml");
2251
                    out.println("<?xml version=\"1.0\"?>");
2252
                    out.println("<error>");
2253
                    //out.println("Error deleting document!!!");
2254
                    out.println(ane.getMessage());
2255
                    out.println("</error>");
2256
                    logMetacat.error("Document could not be deleted: " 
2257
                    		+ ane.getMessage());
2258
                }
2259
            }
2260
            catch (Exception e) {
2261
                response.setContentType("text/xml");
2262
                out.println("<?xml version=\"1.0\"?>");
2263
                out.println("<error>");
2264
                out.println(e.getMessage());
2265
                out.println("</error>");
2266
                logMetacat.error("Document could not be deleted: " 
2267
                		+ e.getMessage());
2268
            }
2269
        }
2270
    }
2271

    
2272
    /**
2273
     * Handle the validation request and return the results to the requestor
2274
     */
2275
    private void handleValidateAction(PrintWriter out, Hashtable params)
2276
    {
2277

    
2278
        // Get the document indicated
2279
        String valtext = null;
2280
        DBConnection dbConn = null;
2281
        int serialNumber = -1;
2282

    
2283
        try {
2284
            valtext = ((String[]) params.get("valtext"))[0];
2285
        } catch (Exception nullpe) {
2286

    
2287
            String docid = null;
2288
            try {
2289
                // Find the document id number
2290
                docid = ((String[]) params.get("docid"))[0];
2291

    
2292
                // Get the document indicated from the db
2293
                DocumentImpl xmldoc = new DocumentImpl(docid);
2294
                valtext = xmldoc.toString();
2295

    
2296
            } catch (NullPointerException npe) {
2297

    
2298
                out.println("<error>Error getting document ID: " + docid
2299
                        + "</error>");
2300
                //if ( conn != null ) { util.returnConnection(conn); }
2301
                return;
2302
            } catch (Exception e) {
2303

    
2304
                out.println(e.getMessage());
2305
            }
2306
        }
2307

    
2308
        try {
2309
            // get a connection from the pool
2310
            dbConn = DBConnectionPool
2311
                    .getDBConnection("MetaCatServlet.handleValidateAction");
2312
            serialNumber = dbConn.getCheckOutSerialNumber();
2313
            DBValidate valobj = new DBValidate(dbConn);
2314
            boolean valid = valobj.validateString(valtext);
2315

    
2316
            // set content type and other response header fields first
2317

    
2318
            out.println(valobj.returnErrors());
2319

    
2320
        } catch (NullPointerException npe2) {
2321
            // set content type and other response header fields first
2322

    
2323
            out.println("<error>Error validating document.</error>");
2324
        } catch (Exception e) {
2325

    
2326
            out.println(e.getMessage());
2327
        } finally {
2328
            // Return db connection
2329
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2330
        }
2331
    }
2332

    
2333
    /**
2334
     * Handle "getrevsionanddoctype" action Given a docid, return it's current
2335
     * revision and doctype from data base The output is String look like
2336
     * "rev;doctype"
2337
     */
2338
    private void handleGetRevisionAndDocTypeAction(PrintWriter out,
2339
            Hashtable params)
2340
    {
2341
        // To store doc parameter
2342
        String[] docs = new String[10];
2343
        // Store a single doc id
2344
        String givenDocId = null;
2345
        // Get docid from parameters
2346
        if (params.containsKey("docid")) {
2347
            docs = (String[]) params.get("docid");
2348
        }
2349
        // Get first docid form string array
2350
        givenDocId = docs[0];
2351

    
2352
        try {
2353
            // Make sure there is a docid
2354
            if (givenDocId == null || givenDocId.equals("")) { throw new Exception(
2355
                    "User didn't specify docid!"); }//if
2356

    
2357
            // Create a DBUtil object
2358
            DBUtil dbutil = new DBUtil();
2359
            // Get a rev and doctype
2360
            String revAndDocType = dbutil
2361
                    .getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
2362
            out.println(revAndDocType);
2363

    
2364
        } catch (Exception e) {
2365
            // Handle exception
2366
            out.println("<?xml version=\"1.0\"?>");
2367
            out.println("<error>");
2368
            out.println(e.getMessage());
2369
            out.println("</error>");
2370
        }
2371

    
2372
    }
2373

    
2374
    /**
2375
     * Handle "getaccesscontrol" action. Read Access Control List from db
2376
     * connection in XML format
2377
     */
2378
    private void handleGetAccessControlAction(PrintWriter out,
2379
            Hashtable params, HttpServletResponse response, String username,
2380
            String[] groupnames)
2381
    {
2382
        DBConnection dbConn = null;
2383
        int serialNumber = -1;
2384
        String docid = ((String[]) params.get("docid"))[0];
2385

    
2386
        try {
2387

    
2388
            // get connection from the pool
2389
            dbConn = DBConnectionPool
2390
                    .getDBConnection("MetaCatServlet.handleGetAccessControlAction");
2391
            serialNumber = dbConn.getCheckOutSerialNumber();
2392
            AccessControlList aclobj = new AccessControlList(dbConn);
2393
            String acltext = aclobj.getACL(docid, username, groupnames);
2394
            out.println(acltext);
2395

    
2396
        } catch (Exception e) {
2397
            out.println("<?xml version=\"1.0\"?>");
2398
            out.println("<error>");
2399
            out.println(e.getMessage());
2400
            out.println("</error>");
2401
        } finally {
2402
            // Retrun db connection to pool
2403
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2404
        }
2405
    }
2406

    
2407
    /**
2408
     * Handle the "getprincipals" action. Read all principals from
2409
     * authentication scheme in XML format
2410
     */
2411
    private void handleGetPrincipalsAction(PrintWriter out, String user,
2412
            String password)
2413
    {
2414
        try {
2415
            AuthSession auth = new AuthSession();
2416
            String principals = auth.getPrincipals(user, password);
2417
            out.println(principals);
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
        }
2425
    }
2426

    
2427
    /**
2428
     * Handle "getdoctypes" action. Read all doctypes from db connection in XML
2429
     * format
2430
     */
2431
    private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
2432
            HttpServletResponse response)
2433
    {
2434
        try {
2435
            DBUtil dbutil = new DBUtil();
2436
            String doctypes = dbutil.readDoctypes();
2437
            out.println(doctypes);
2438
        } catch (Exception e) {
2439
            out.println("<?xml version=\"1.0\"?>");
2440
            out.println("<error>");
2441
            out.println(e.getMessage());
2442
            out.println("</error>");
2443
        }
2444
    }
2445

    
2446
    /**
2447
     * Handle the "getdtdschema" action. Read DTD or Schema file for a given
2448
     * doctype from Metacat catalog system
2449
     */
2450
    private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
2451
            HttpServletResponse response)
2452
    {
2453

    
2454
        String doctype = null;
2455
        String[] doctypeArr = (String[]) params.get("doctype");
2456

    
2457
        // get only the first doctype specified in the list of doctypes
2458
        // it could be done for all doctypes in that list
2459
        if (doctypeArr != null) {
2460
            doctype = ((String[]) params.get("doctype"))[0];
2461
        }
2462

    
2463
        try {
2464
            DBUtil dbutil = new DBUtil();
2465
            String dtdschema = dbutil.readDTDSchema(doctype);
2466
            out.println(dtdschema);
2467

    
2468
        } catch (Exception e) {
2469
            out.println("<?xml version=\"1.0\"?>");
2470
            out.println("<error>");
2471
            out.println(e.getMessage());
2472
            out.println("</error>");
2473
        }
2474

    
2475
    }
2476

    
2477
    /**
2478
     * Handle the "getlastdocid" action. Get the latest docid with rev number
2479
     * from db connection in XML format
2480
     */
2481
    private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
2482
            HttpServletResponse response)
2483
    {
2484

    
2485
        String scope = ((String[]) params.get("scope"))[0];
2486
        if (scope == null) {
2487
            scope = ((String[]) params.get("username"))[0];
2488
        }
2489

    
2490
        try {
2491

    
2492
            DBUtil dbutil = new DBUtil();
2493
            String lastDocid = dbutil.getMaxDocid(scope);
2494
            out.println("<?xml version=\"1.0\"?>");
2495
            out.println("<lastDocid>");
2496
            out.println("  <scope>" + scope + "</scope>");
2497
            out.println("  <docid>" + lastDocid + "</docid>");
2498
            out.println("</lastDocid>");
2499

    
2500
        } catch (Exception e) {
2501
            out.println("<?xml version=\"1.0\"?>");
2502
            out.println("<error>");
2503
            out.println(e.getMessage());
2504
            out.println("</error>");
2505
        }
2506
    }
2507

    
2508
    /**
2509
     * Print a report from the event log based on filter parameters passed in
2510
     * from the web.
2511
     *
2512
     * @param params the parameters from the web request
2513
     * @param request the http request object for getting request details
2514
     * @param response the http response object for writing output
2515
     */
2516
    private void handleGetLogAction(Hashtable params, HttpServletRequest request,
2517
            HttpServletResponse response, String username, String[] groups)
2518
    {
2519
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2520
        try {
2521
            response.setContentType("text/xml");
2522
            PrintWriter out = response.getWriter();
2523

    
2524
            // Check that the user is authenticated as an administrator account
2525
            if (!MetaCatUtil.isAdministrator(username, groups)) {
2526
                out.print("<error>");
2527
                out.print("The user \"" + username +
2528
                        "\" is not authorized for this action.");
2529
                out.print("</error>");
2530
                return;
2531
            }
2532

    
2533
            // Get all of the parameters in the correct formats
2534
            String[] ipAddress = (String[])params.get("ipaddress");
2535
            String[] principal = (String[])params.get("principal");
2536
            String[] docid = (String[])params.get("docid");
2537
            String[] event = (String[])params.get("event");
2538
            String[] startArray = (String[]) params.get("start");
2539
            String[] endArray = (String[]) params.get("end");
2540
            String start = null;
2541
            String end = null;
2542
            if (startArray != null) {
2543
                start = startArray[0];
2544
            }
2545
            if (endArray != null) {
2546
                end = endArray[0];
2547
            }
2548
            Timestamp startDate = null;
2549
            Timestamp endDate = null;
2550
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
2551
            try {
2552
                if (start != null) {
2553
                    startDate = new Timestamp((format.parse(start)).getTime());
2554
                }
2555
                if (end != null) {
2556
                    endDate = new Timestamp((format.parse(end)).getTime());
2557
                }
2558
            } catch (ParseException e) {
2559
                System.out.println("Failed to created Timestamp from input.");
2560
            }
2561

    
2562
            // Request the report by passing the filter parameters
2563
            out.println(EventLog.getInstance().getReport(ipAddress, principal,
2564
                    docid, event, startDate, endDate));
2565
            out.close();
2566
        } catch (IOException e) {
2567
            logMetacat.error(
2568
                    "Could not open http response for writing: " + e.getMessage());
2569
        }
2570
    }
2571

    
2572
    /**
2573
     * Rebuild the index for one or more documents. If the docid parameter is
2574
     * provided, rebuild for just that one document or list of documents. If
2575
     * not, then rebuild the index for all documents in the xml_documents
2576
     * table.
2577
     *
2578
     * @param params the parameters from the web request
2579
     * @param request the http request object for getting request details
2580
     * @param response the http response object for writing output
2581
     * @param username the username of the authenticated user
2582
     */
2583
    private void handleBuildIndexAction(Hashtable params,
2584
            HttpServletRequest request, HttpServletResponse response,
2585
            String username, String[] groups)
2586
    {
2587
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2588
        
2589
        // Get all of the parameters in the correct formats
2590
        String[] docid = (String[])params.get("docid");
2591

    
2592
        // Rebuild the indices for appropriate documents
2593
        try {
2594
            response.setContentType("text/xml");
2595
            PrintWriter out = response.getWriter();
2596

    
2597
            // Check that the user is authenticated as an administrator account
2598
            if (!MetaCatUtil.isAdministrator(username, groups)) {
2599
                out.print("<error>");
2600
                out.print("The user \"" + username +
2601
                        "\" is not authorized for this action.");
2602
                out.print("</error>");
2603
                return;
2604
            }
2605

    
2606
            // Process the documents
2607
            out.println("<success>");
2608
            if (docid == null || docid.length == 0) {
2609
                // Process all of the documents
2610
                try {
2611
                    Vector documents = getDocumentList();
2612
                    Iterator it = documents.iterator();
2613
                    while (it.hasNext()) {
2614
                        String id = (String) it.next();
2615
                        buildDocumentIndex(id, out);
2616
                    }
2617
                } catch (SQLException se) {
2618
                    out.print("<error>");
2619
                    out.print(se.getMessage());
2620
                    out.println("</error>");
2621
                }
2622
            } else {
2623
                // Only process the requested documents
2624
                for (int i = 0; i < docid.length; i++) {
2625
                    buildDocumentIndex(docid[i], out);
2626
                }
2627
            }
2628
            out.println("</success>");
2629
            out.close();
2630
        } catch (IOException e) {
2631
            logMetacat.error(
2632
                    "Could not open http response for writing: "
2633
                    + e.getMessage());
2634
        }
2635
    }
2636

    
2637
    /**
2638
     * Build the index for one document by reading the document and
2639
     * calling its buildIndex() method.
2640
     *
2641
     * @param docid the document (with revision) to rebuild
2642
     * @param out the PrintWriter to which output is printed
2643
     */
2644
    private void buildDocumentIndex(String docid, PrintWriter out)
2645
    {
2646
        try {
2647
            DocumentImpl doc = new DocumentImpl(docid, false);
2648
            doc.buildIndex();
2649
            out.print("<docid>" + docid);
2650
            out.println("</docid>");
2651
        } catch (McdbException me) {
2652
            out.print("<error>");
2653
            out.print(me.getMessage());
2654
            out.println("</error>");
2655
        }
2656
    }
2657

    
2658
    /**
2659
     * Handle documents passed to metacat that are encoded using the
2660
     * "multipart/form-data" mime type. This is typically used for uploading
2661
     * data files which may be binary and large.
2662
     */
2663
    private void handleMultipartForm(HttpServletRequest request,
2664
            HttpServletResponse response)
2665
    {
2666
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2667
        PrintWriter out = null;
2668
        String action = null;
2669

    
2670
        // Parse the multipart form, and save the parameters in a Hashtable and
2671
        // save the FileParts in a hashtable
2672

    
2673
        Hashtable params = new Hashtable();
2674
        Hashtable fileList = new Hashtable();
2675
        int sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit")))
2676
                .intValue();
2677
        logMetacat.info(
2678
                "The size limit of uploaded data files is: " + sizeLimit);
2679

    
2680
        try {
2681
            MultipartParser mp = new MultipartParser(request,
2682
                    sizeLimit * 1024 * 1024);
2683
            Part part;
2684
            while ((part = mp.readNextPart()) != null) {
2685
                String name = part.getName();
2686

    
2687
                if (part.isParam()) {
2688
                    // it's a parameter part
2689
                    ParamPart paramPart = (ParamPart) part;
2690
                    String value = paramPart.getStringValue();
2691
                    params.put(name, value);
2692
                    if (name.equals("action")) {
2693
                        action = value;
2694
                    }
2695
                } else if (part.isFile()) {
2696
                    // it's a file part
2697
                    FilePart filePart = (FilePart) part;
2698
                    fileList.put(name, filePart);
2699

    
2700
                    // Stop once the first file part is found, otherwise going
2701
                    // onto the
2702
                    // next part prevents access to the file contents. So...for
2703
                    // upload
2704
                    // to work, the datafile must be the last part
2705
                    break;
2706
                }
2707
            }
2708
        } catch (IOException ioe) {
2709
            try {
2710
                out = response.getWriter();
2711
            } catch (IOException ioe2) {
2712
                logMetacat.fatal("Fatal Error: couldn't get response output stream.");
2713
            }
2714
            out.println("<?xml version=\"1.0\"?>");
2715
            out.println("<error>");
2716
            out.println("Error: problem reading multipart data.");
2717
            out.println("</error>");
2718
        }
2719

    
2720
        // Get the session information
2721
        String username = null;
2722
        String password = null;
2723
        String[] groupnames = null;
2724
        String sess_id = null;
2725

    
2726
        // be aware of session expiration on every request
2727
        HttpSession sess = request.getSession(true);
2728
        if (sess.isNew()) {
2729
            // session expired or has not been stored b/w user requests
2730
            username = "public";
2731
            sess.setAttribute("username", username);
2732
        } else {
2733
            username = (String) sess.getAttribute("username");
2734
            password = (String) sess.getAttribute("password");
2735
            groupnames = (String[]) sess.getAttribute("groupnames");
2736
            try {
2737
                sess_id = (String) sess.getId();
2738
            } catch (IllegalStateException ise) {
2739
                System.out
2740
                        .println("error in  handleMultipartForm: this shouldn't "
2741
                                + "happen: the session should be valid: "
2742
                                + ise.getMessage());
2743
            }
2744
        }
2745

    
2746
        // Get the out stream
2747
        try {
2748
            out = response.getWriter();
2749
        } catch (IOException ioe2) {
2750
            logMetacat.error("Fatal Error: couldn't get response "
2751
                    + "output stream.");
2752
        }
2753

    
2754
        if (action.equals("upload")) {
2755
            if (username != null && !username.equals("public")) {
2756
                handleUploadAction(request, out, params, fileList, username,
2757
                        groupnames);
2758
            } else {
2759

    
2760
                out.println("<?xml version=\"1.0\"?>");
2761
                out.println("<error>");
2762
                out.println("Permission denied for " + action);
2763
                out.println("</error>");
2764
            }
2765
        } else {
2766
            /*
2767
             * try { out = response.getWriter(); } catch (IOException ioe2) {
2768
             * System.err.println("Fatal Error: couldn't get response output
2769
             * stream.");
2770
             */
2771
            out.println("<?xml version=\"1.0\"?>");
2772
            out.println("<error>");
2773
            out.println(
2774
                    "Error: action not registered.  Please report this error.");
2775
            out.println("</error>");
2776
        }
2777
        out.close();
2778
    }
2779

    
2780
    /**
2781
     * Handle the upload action by saving the attached file to disk and
2782
     * registering it in the Metacat db
2783
     */
2784
    private void handleUploadAction(HttpServletRequest request,
2785
            PrintWriter out, Hashtable params, Hashtable fileList,
2786
            String username, String[] groupnames)
2787
    {
2788
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2789
        //PrintWriter out = null;
2790
        //Connection conn = null;
2791
        String action = null;
2792
        String docid = null;
2793

    
2794
        /*
2795
         * response.setContentType("text/xml"); try { out =
2796
         * response.getWriter(); } catch (IOException ioe2) {
2797
         * System.err.println("Fatal Error: couldn't get response output
2798
         * stream.");
2799
         */
2800

    
2801
        if (params.containsKey("docid")) {
2802
            docid = (String) params.get("docid");
2803
        }
2804

    
2805
        // Make sure we have a docid and datafile
2806
        if (docid != null && fileList.containsKey("datafile")) {
2807
            logMetacat.info("Uploading data docid: " + docid);
2808
            // Get a reference to the file part of the form
2809
            FilePart filePart = (FilePart) fileList.get("datafile");
2810
            String fileName = filePart.getFileName();
2811
            logMetacat.info("Uploading filename: " + fileName);
2812
            // Check if the right file existed in the uploaded data
2813
            if (fileName != null) {
2814

    
2815
                try {
2816
                    //logMetacat.info("Upload datafile " + docid
2817
                    // +"...", 10);
2818
                    //If document get lock data file grant
2819
                    if (DocumentImpl.getDataFileLockGrant(docid)) {
2820
                        // Save the data file to disk using "docid" as the name
2821
                        String datafilepath = MetaCatUtil.getOption("datafilepath");
2822
                        File dataDirectory = new File(datafilepath);
2823
                        dataDirectory.mkdirs();
2824
                        File newFile = null;
2825
                        long size = 0;
2826
                        try
2827
                        {
2828
                          newFile = new File(dataDirectory, docid);
2829
                          size = filePart.writeTo(newFile);
2830
                        
2831
//                        register the file in the database (which generates
2832
                          // an exception
2833
                          //if the docid is not acceptable or other untoward
2834
                          // things happen
2835
                          DocumentImpl.registerDocument(fileName, "BIN", docid,
2836
                                username, groupnames);
2837
                        }
2838
                        catch (Exception ee)
2839
                        {
2840
                           //detelte the file to create
2841
                            newFile.delete();
2842
                            throw ee;
2843
                        }
2844

    
2845
                        EventLog.getInstance().log(request.getRemoteAddr(),
2846
                                username, docid, "upload");
2847
                        // Force replication this data file
2848
                        // To data file, "insert" and update is same
2849
                        // The fourth parameter is null. Because it is
2850
                        // notification server
2851
                        // and this method is in MetaCatServerlet. It is
2852
                        // original command,
2853
                        // not get force replication info from another metacat
2854
                        ForceReplicationHandler frh = new ForceReplicationHandler(
2855
                                docid, "insert", false, null);
2856

    
2857
                        // set content type and other response header fields
2858
                        // first
2859
                        out.println("<?xml version=\"1.0\"?>");
2860
                        out.println("<success>");
2861
                        out.println("<docid>" + docid + "</docid>");
2862
                        out.println("<size>" + size + "</size>");
2863
                        out.println("</success>");
2864
                    }
2865

    
2866
                } catch (Exception e) {
2867
                    
2868
                    out.println("<?xml version=\"1.0\"?>");
2869
                    out.println("<error>");
2870
                    out.println(e.getMessage());
2871
                    out.println("</error>");
2872
                }
2873
            } else {
2874
                // the field did not contain a file
2875
                out.println("<?xml version=\"1.0\"?>");
2876
                out.println("<error>");
2877
                out.println("The uploaded data did not contain a valid file.");
2878
                out.println("</error>");
2879
            }
2880
        } else {
2881
            // Error bcse docid missing or file missing
2882
            out.println("<?xml version=\"1.0\"?>");
2883
            out.println("<error>");
2884
            out.println("The uploaded data did not contain a valid docid "
2885
                    + "or valid file.");
2886
            out.println("</error>");
2887
        }
2888
    }
2889

    
2890
    /*
2891
     * A method to handle set access action
2892
     */
2893
    private void handleSetAccessAction(PrintWriter out, Hashtable params,
2894
            String username)
2895
    {
2896
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2897
        String[] docList = null;
2898
        String[] principalList = null;
2899
        String[] permissionList = null;
2900
        String[] permTypeList = null;
2901
        String[] permOrderList = null;
2902
        String permission = null;
2903
        String permType = null;
2904
        String permOrder = null;
2905
        Vector errorList = new Vector();
2906
        String error = null;
2907
        Vector successList = new Vector();
2908
        String success = null;
2909

    
2910
        // Get parameters
2911
        if (params.containsKey("docid")) {
2912
            docList = (String[]) params.get("docid");
2913
        }
2914
        if (params.containsKey("principal")) {
2915
            principalList = (String[]) params.get("principal");
2916
        }
2917
        if (params.containsKey("permission")) {
2918
            permissionList = (String[]) params.get("permission");
2919

    
2920
        }
2921
        if (params.containsKey("permType")) {
2922
            permTypeList = (String[]) params.get("permType");
2923

    
2924
        }
2925
        if (params.containsKey("permOrder")) {
2926
            permOrderList = (String[]) params.get("permOrder");
2927

    
2928
        }
2929

    
2930
        // Make sure the parameter is not null
2931
        if (docList == null || principalList == null || permTypeList == null
2932
                || permissionList == null) {
2933
            error = "Please check your parameter list, it should look like: "
2934
                    + "?action=setaccess&docid=pipeline.1.1&principal=public"
2935
                    + "&permission=read&permType=allow&permOrder=allowFirst";
2936
            errorList.addElement(error);
2937
            outputResponse(successList, errorList, out);
2938
            return;
2939
        }
2940

    
2941
        // Only select first element for permission, type and order
2942
        permission = permissionList[0];
2943
        permType = permTypeList[0];
2944
        if (permOrderList != null) {
2945
            permOrder = permOrderList[0];
2946
        }
2947

    
2948
        // Get package doctype set
2949
        Vector packageSet = MetaCatUtil.getOptionList(MetaCatUtil
2950
                .getOption("packagedoctypeset"));
2951
        //debug
2952
        if (packageSet != null) {
2953
            for (int i = 0; i < packageSet.size(); i++) {
2954
                logMetacat.debug("doctype in package set: "
2955
                        + (String) packageSet.elementAt(i));
2956
            }
2957
        }
2958

    
2959
        // handle every accessionNumber
2960
        for (int i = 0; i < docList.length; i++) {
2961
            String accessionNumber = docList[i];
2962
            String owner = null;
2963
            String publicId = null;
2964
            // Get document owner and public id
2965
            try {
2966
                owner = getFieldValueForDoc(accessionNumber, "user_owner");
2967
                publicId = getFieldValueForDoc(accessionNumber, "doctype");
2968
            } catch (Exception e) {
2969
                logMetacat.error("Error in handleSetAccessAction: "
2970
                        + e.getMessage());
2971
                error = "Error in set access control for document - "
2972
                        + accessionNumber + e.getMessage();
2973
                errorList.addElement(error);
2974
                continue;
2975
            }
2976
            //check if user is the owner. Only owner can do owner
2977
            if (username == null || owner == null || !username.equals(owner)) {
2978
                error = "User - " + username
2979
                        + " does not have permission to set "
2980
                        + "access control for docid - " + accessionNumber;
2981
                errorList.addElement(error);
2982
                continue;
2983
            }
2984

    
2985
            // If docid publicid is BIN data file or other beta4, 6 package
2986
            // document
2987
            // we could not do set access control. Because we don't want
2988
            // inconsistent
2989
            // to its access docuemnt
2990
            if (publicId != null && packageSet != null
2991
                    && packageSet.contains(publicId)) {
2992
                error = "Could not set access control to document "
2993
                        + accessionNumber
2994
                        + "because it is in a pakcage and it has a access file for it";
2995
                errorList.addElement(error);
2996
                continue;
2997
            }
2998

    
2999
            // for every principle
3000
            for (int j = 0; j < principalList.length; j++) {
3001
                String principal = principalList[j];
3002
                try {
3003
                    //insert permission
3004
                    AccessControlForSingleFile accessControl = new AccessControlForSingleFile(
3005
                            accessionNumber, principal, permission, permType,
3006
                            permOrder);
3007
                    accessControl.insertPermissions();
3008
                    success = "Set access control to document "
3009
                            + accessionNumber + " successfully";
3010
                    successList.addElement(success);
3011
                } catch (Exception ee) {
3012
                    logMetacat.error(
3013
                            "Erorr in handleSetAccessAction2: "
3014
                                    + ee.getMessage());
3015
                    error = "Faild to set access control for document "
3016
                            + accessionNumber + " because " + ee.getMessage();
3017
                    errorList.addElement(error);
3018
                    continue;
3019
                }
3020
            }
3021
        }
3022
        outputResponse(successList, errorList, out);
3023
    }
3024

    
3025
    /*
3026
     * A method try to determin a docid's public id, if couldn't find null will
3027
     * be returned.
3028
     */
3029
    private String getFieldValueForDoc(String accessionNumber, String fieldName)
3030
            throws Exception
3031
    {
3032
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
3033
        if (accessionNumber == null || accessionNumber.equals("")
3034
                || fieldName == null || fieldName.equals("")) { throw new Exception(
3035
                "Docid or field name was not specified"); }
3036

    
3037
        PreparedStatement pstmt = null;
3038
        ResultSet rs = null;
3039
        String fieldValue = null;
3040
        String docId = null;
3041
        DBConnection conn = null;
3042
        int serialNumber = -1;
3043

    
3044
        // get rid of revision if access number has
3045
        docId = MetaCatUtil.getDocIdFromString(accessionNumber);
3046
        try {
3047
            //check out DBConnection
3048
            conn = DBConnectionPool
3049
                    .getDBConnection("MetaCatServlet.getPublicIdForDoc");
3050
            serialNumber = conn.getCheckOutSerialNumber();
3051
            pstmt = conn.prepareStatement("SELECT " + fieldName
3052
                    + " FROM xml_documents " + "WHERE docid = ? ");
3053

    
3054
            pstmt.setString(1, docId);
3055
            pstmt.execute();
3056
            rs = pstmt.getResultSet();
3057
            boolean hasRow = rs.next();
3058
            int perm = 0;
3059
            if (hasRow) {
3060
                fieldValue = rs.getString(1);
3061
            } else {
3062
                throw new Exception("Could not find document: "
3063
                        + accessionNumber);
3064
            }
3065
        } catch (Exception e) {
3066
            logMetacat.error(
3067
                    "Exception in MetacatServlet.getPublicIdForDoc: "
3068
                            + e.getMessage());
3069
            throw e;
3070
        } finally {
3071
            try {
3072
                rs.close();
3073
                pstmt.close();
3074

    
3075
            } finally {
3076
                DBConnectionPool.returnDBConnection(conn, serialNumber);
3077
            }
3078
        }
3079
        return fieldValue;
3080
    }
3081

    
3082
    /*
3083
     * Get the list of documents from the database and return the list in an
3084
     * Vector of identifiers.
3085
     *
3086
     * @ returns the array of identifiers
3087
     */
3088
    private Vector getDocumentList() throws SQLException
3089
    {
3090
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
3091
        Vector docList = new Vector();
3092
        PreparedStatement pstmt = null;
3093
        ResultSet rs = null;
3094
        DBConnection conn = null;
3095
        int serialNumber = -1;
3096

    
3097
        try {
3098
            //check out DBConnection
3099
            conn = DBConnectionPool
3100
                    .getDBConnection("MetaCatServlet.getDocumentList");
3101
            serialNumber = conn.getCheckOutSerialNumber();
3102
            pstmt = conn.prepareStatement("SELECT docid, rev"
3103
                    + " FROM xml_documents ");
3104
            pstmt.execute();
3105
            rs = pstmt.getResultSet();
3106
            while (rs.next()) {
3107
                String docid = rs.getString(1);
3108
                String rev = rs.getString(2);
3109
                docList.add(docid + "." + rev);
3110
            }
3111
        } catch (SQLException e) {
3112
            logMetacat.error(
3113
                    "Exception in MetacatServlet.getDocumentList: "
3114
                            + e.getMessage());
3115
            throw e;
3116
        } finally {
3117
            try {
3118
                rs.close();
3119
                pstmt.close();
3120

    
3121
            } catch (SQLException se) {
3122
                logMetacat.error(
3123
                    "Exception in MetacatServlet.getDocumentList: "
3124
                            + se.getMessage());
3125
                throw se;
3126
            } finally {
3127
                DBConnectionPool.returnDBConnection(conn, serialNumber);
3128
            }
3129
        }
3130
        return docList;
3131
    }
3132

    
3133
    /*
3134
     * A method to output setAccess action result
3135
     */
3136
    private void outputResponse(Vector successList, Vector errorList,
3137
            PrintWriter out)
3138
    {
3139
        boolean error = false;
3140
        boolean success = false;
3141
        // Output prolog
3142
        out.println(PROLOG);
3143
        // output success message
3144
        if (successList != null) {
3145
            for (int i = 0; i < successList.size(); i++) {
3146
                out.println(SUCCESS);
3147
                out.println((String) successList.elementAt(i));
3148
                out.println(SUCCESSCLOSE);
3149
                success = true;
3150
            }
3151
        }
3152
        // output error message
3153
        if (errorList != null) {
3154
            for (int i = 0; i < errorList.size(); i++) {
3155
                out.println(ERROR);
3156
                out.println((String) errorList.elementAt(i));
3157
                out.println(ERRORCLOSE);
3158
                error = true;
3159
            }
3160
        }
3161

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