Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that implements a metadata catalog as a java Servlet
4
 *  Copyright: 2000 Regents of the University of California and the
5
 *             National Center for Ecological Analysis and Synthesis
6
 *    Authors: Matt Jones, Dan Higgins, Jivka Bojilova, Chad Berkley
7
 *    Release: @release@
8
 *
9
 *   '$Author: jones $'
10
 *     '$Date: 2006-02-24 18:15:51 -0800 (Fri, 24 Feb 2006) $'
11
 * '$Revision: 2922 $'
12
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26
 */
27

    
28
package edu.ucsb.nceas.metacat;
29

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

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

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

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

    
72
import edu.ucsb.nceas.utilities.Options;
73
import edu.ucsb.nceas.metacat.spatial.MetacatSpatialQuery;
74
import edu.ucsb.nceas.metacat.spatial.MetacatSpatialDocument;
75
import edu.ucsb.nceas.metacat.spatial.MetacatSpatialDataset;
76
import edu.ucsb.nceas.metacat.spatial.MetacatSpatialConstants;
77

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

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

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

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

    
176
            // initiate the indexing Queue
177
            IndexingQueue.getInstance();
178
            
179
            // start the IndexingThread if indexingTimerTaskTime more than 0. 
180
            // It will index all the documents not yet indexed in the database             
181
            int indexingTimerTaskTime = Integer.parseInt(MetaCatUtil.getOption("indexingTimerTaskTime"));
182
            if(indexingTimerTaskTime > 0){
183
            	timer = new Timer();
184
            	timer.schedule(new IndexingTimerTask(), 0, indexingTimerTaskTime);
185
            }
186
            
187
            // read the config files: 
188
            Vector skins = MetaCatUtil.getOptionList(MetaCatUtil.getOption("skinconfigfiles"));
189
            String skinName, skinDirPath = null;
190
            File skinPropertyFile = null;
191
           
192
            for (int i = 0; i < skins.size(); i++) {
193
            	skinName = (String) skins.elementAt(i);
194
                skinDirPath = context.getRealPath(CONFIG_DIR + "/skin.configs/" + skinName);
195
                skinPropertyFile = new File(skinDirPath, skinName + ".properties"); 
196
                Properties skinOption = null;
197
                try	{
198
                	skinOption = new Properties();
199
                    FileInputStream fis = new FileInputStream(skinPropertyFile);
200
                    skinOption.load(fis);
201
                    fis.close();
202
                } catch (IOException ioe) {
203
                    Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
204
                    logMetacat.error("Error in loading options for skin " + "skinName" +" : "
205
                            + ioe.getMessage());
206
                }                
207
                MetaCatUtil.skinconfigs.put(skinName, skinOption);
208
            }
209
           
210
            // create a spatial index of the database
211
            MetacatSpatialConstants.setServerContext(MetaCatUtil.getOption("server"));
212
            MetacatSpatialQuery  _spatialQuery = new MetacatSpatialQuery();
213
            
214
            // issue the query  -- using the geographic bounds of the Earth
215
            MetacatSpatialDataset _data = _spatialQuery.queryDatasetByCartesianBounds(-180, -90, 180, 90);
216
            
217
            // write the data to the appropriate theme 
218
            _data.writeMetacatSpatialCache();
219
           
220
           
221
            MetaCatUtil.printMessage("Metacat (" + Version.getVersion()
222
                               + ") initialized.");
223

    
224
        } catch (ServletException ex) {
225
            throw ex;
226
        } catch (SQLException e) {
227
            Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
228
            logMetacat.error("Error in MetacatServlet.init: "
229
                    + e.getMessage());
230
        }
231
    }
232

    
233
    /**
234
     * Close all db connections from the pool
235
     */
236
    public void destroy()
237
    {
238
        // Close all db connection
239
        System.out.println("Destroying MetacatServlet");
240
        timer.cancel();
241
        IndexingQueue.getInstance().setMetacatRunning(false);
242
        DBConnectionPool.release();
243
    }
244

    
245
    /** Handle "GET" method requests from HTTP clients */
246
    public void doGet(HttpServletRequest request, HttpServletResponse response)
247
            throws ServletException, IOException
248
    {
249

    
250
        // Process the data and send back the response
251
        handleGetOrPost(request, response);
252
    }
253

    
254
    /** Handle "POST" method requests from HTTP clients */
255
    public void doPost(HttpServletRequest request, HttpServletResponse response)
256
            throws ServletException, IOException
257
    {
258

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

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

    
401
    /**
402
     * Control servlet response depending on the action parameter specified
403
     */
404
    private void handleGetOrPost(HttpServletRequest request,
405
            HttpServletResponse response) throws ServletException, IOException
406
    {
407
        MetaCatUtil util = new MetaCatUtil();
408
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
409
        
410
        /*
411
         * logMetacat.debug("Connection pool size: "
412
         * +connPool.getSizeOfDBConnectionPool(),10);
413
         * logMetacat.debug("Free DBConnection number: "
414
         */
415
        //If all DBConnection in the pool are free and DBConnection pool
416
        //size is greater than initial value, shrink the connection pool
417
        //size to initial value
418
        DBConnectionPool.shrinkDBConnectionPoolSize();
419

    
420
        //Debug message to print out the method which have a busy DBConnection
421
        try {
422
            DBConnectionPool pool = DBConnectionPool.getInstance();
423
            pool.printMethodNameHavingBusyDBConnection();
424
        } catch (SQLException e) {
425
            logMetacat.error("Error in MetacatServlet.handleGetOrPost: "
426
                    + e.getMessage());
427
            e.printStackTrace();
428
        }
429

    
430
        String ctype = request.getContentType();
431
        if (ctype != null && ctype.startsWith("multipart/form-data")) {
432
            handleMultipartForm(request, response);
433
        } else {
434

    
435
            String name = null;
436
            String[] value = null;
437
            String[] docid = new String[3];
438
            Hashtable params = new Hashtable();
439
            Enumeration paramlist = request.getParameterNames();
440

    
441
            while (paramlist.hasMoreElements()) {
442

    
443
                name = (String) paramlist.nextElement();
444
                value = request.getParameterValues(name);
445

    
446
                // Decode the docid and mouse click information
447
                if (name.endsWith(".y")) {
448
                    docid[0] = name.substring(0, name.length() - 2);
449
                    params.put("docid", docid);
450
                    name = "ypos";
451
                }
452
                if (name.endsWith(".x")) {
453
                    name = "xpos";
454
                }
455

    
456
                params.put(name, value);
457
            }
458

    
459
            //handle param is emptpy
460
            if (params.isEmpty() || params == null) { return; }
461

    
462
            //if the user clicked on the input images, decode which image
463
            //was clicked then set the action.
464
            if(params.get("action") == null){
465
                PrintWriter out = response.getWriter();
466
                response.setContentType("text/xml");
467
                out.println("<?xml version=\"1.0\"?>");
468
                out.println("<error>");
469
                out.println("Action not specified");
470
                out.println("</error>");
471
                out.close();
472
                return;
473
            }
474

    
475
            String action = ((String[]) params.get("action"))[0];
476
            logMetacat.info("Action is: " + action);
477

    
478
            // This block handles session management for the servlet
479
            // by looking up the current session information for all actions
480
            // other than "login" and "logout"
481
            String username = null;
482
            String password = null;
483
            String[] groupnames = null;
484
            String sess_id = null;
485
            name = null;
486
            
487
            // handle login action
488
            if (action.equals("login")) {
489
                PrintWriter out = response.getWriter();
490
                handleLoginAction(out, params, request, response);
491
                out.close();
492
        
493
                // handle logout action
494
            }   else if (action.equals("logout")) {
495
                PrintWriter out = response.getWriter();
496
                handleLogoutAction(out, params, request, response);
497
                out.close();
498

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

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

    
561
                    username = (String) sess.getAttribute("username");
562
                    logMetacat.info("The user name from session is: "
563
                            + username);
564
                    password = (String) sess.getAttribute("password");
565
                    groupnames = (String[]) sess.getAttribute("groupnames");
566
                    name = (String) sess.getAttribute("name");
567
                }
568

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

    
596
              logMetacat.fatal("******************* SPATIAL QUERY ********************");
597
              logMetacat.fatal("******************* SPATIAL QUERY ********************");
598
              logMetacat.fatal("******************* SPATIAL QUERY ********************");
599
              logMetacat.fatal("******************* SPATIAL QUERY ********************");
600
              logMetacat.fatal("******************* SPATIAL QUERY ********************");
601

    
602
              
603
              PrintWriter out = response.getWriter();
604
              handleSpatialQuery(out, params, response, username, groupnames, sess_id);
605
              out.close();
606
            
607
            } else if (action.equals("export")) {
608

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

    
765
            //util.closeConnections();
766
            // Close the stream to the client
767
            //out.close();
768
        }
769
    }
770

    
771
    /////////////////////////////// METACAT SPATIAL ///////////////////////////
772

    
773
    /**
774
     * handles all spatial queries -- these queries may include any of the 
775
     * queries supported by the WFS / WMS standards
776
     
777
     handleSQuery(out, params, response, username, groupnames,
778
                            sess_id);
779
     */
780
    private void handleSpatialQuery(PrintWriter out, Hashtable params, 
781
                                    HttpServletResponse response,
782
                                    String username, String[] groupnames, 
783
                                    String sess_id) {
784
      
785
      Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
786
      MetacatSpatialQuery _spatialQuery = new MetacatSpatialQuery();
787
      
788
      
789
      // switch -- html/xml print
790
      boolean printXML = false; 
791
      
792
      // get the spatial parameters
793
      logMetacat.warn("params: " +  params);
794
      //String _xmax =  (String)params.get("XMAX");
795
      float _xmax = Float.parseFloat( ((String[]) params.get("XMAX"))[0] );
796
      float _ymax = Float.parseFloat( ((String[]) params.get("YMAX"))[0] );
797
      float _xmin = Float.parseFloat( ((String[]) params.get("XMIN"))[0] );
798
      float _ymin = Float.parseFloat( ((String[]) params.get("YMIN"))[0] );
799
      logMetacat.warn("\nxmax: " + _xmax + " \nymax:" + _ymax +
800
                      "\nxmin: " + _xmin + "\nymin: " + _ymin);
801

    
802

    
803
      // is it UTM or lat/long
804

    
805
      // issue the query 
806
      MetacatSpatialDataset _data =  
807
        _spatialQuery.queryDatasetByCartesianBounds(_xmin, _ymin, _xmax, _ymax);
808

    
809
      // create an s-query
810
      //DocumentIdQuery.createDocidQueryParams(_data.getDocidList(), params);
811
      //params.put("query", DocumentIdQuery.createDocidQuery(_data.getDocidList()) );
812
      String[] queryArray = new String[1];
813
      queryArray[0] = DocumentIdQuery.createDocidQuery(_data.getDocidList());
814
      params.put("query", queryArray);
815
                      
816
      String[] qformatArray = new String[1];
817
      qformatArray[0] = "knp";
818
      params.put("qformat", qformatArray);
819

    
820
      // change the action 
821
      String[] actionArray = new String[1];
822
      actionArray[0] = "squery";
823
      params.put("action", actionArray);
824

    
825
      // return the list of docs and point at the spatial theme 
826
      if ( printXML) {
827
        response.setContentType("text/xml");
828
        out.println(_data.toXML() ); // write the data as xml
829
        out.close();
830
      } else {
831
        logMetacat.warn("username: " + username+"\nsession: "+sess_id);
832
        handleSQuery(out, params, response, username, groupnames, sess_id);  
833
      }
834
      
835
      return;
836
    }
837

    
838

    
839
    // LOGIN & LOGOUT SECTION
840
    /**
841
     * Handle the login request. Create a new session object. Do user
842
     * authentication through the session.
843
     */
844
    private void handleLoginAction(PrintWriter out, Hashtable params,
845
            HttpServletRequest request, HttpServletResponse response)
846
    {
847
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
848
        AuthSession sess = null;
849

    
850
        if(params.get("username") == null){
851
            response.setContentType("text/xml");
852
            out.println("<?xml version=\"1.0\"?>");
853
            out.println("<error>");
854
            out.println("Username not specified");
855
            out.println("</error>");
856
            return;
857
        }
858

    
859
        //}
860

    
861
        if(params.get("password") == null){
862
            response.setContentType("text/xml");
863
            out.println("<?xml version=\"1.0\"?>");
864
            out.println("<error>");
865
            out.println("Password not specified");
866
            out.println("</error>");
867
            return;
868
        }
869

    
870
        String un = ((String[]) params.get("username"))[0];
871
        logMetacat.info("user " + un + " is trying to login");
872
        String pw = ((String[]) params.get("password"))[0];
873

    
874
        String qformat = "xml";
875
        if(params.get("qformat") != null){
876
            qformat = ((String[]) params.get("qformat"))[0];
877
        }
878

    
879
        try {
880
            sess = new AuthSession();
881
        } catch (Exception e) {
882
            System.out.println("error in MetacatServlet.handleLoginAction: "
883
                    + e.getMessage());
884
            out.println(e.getMessage());
885
            return;
886
        }
887
        boolean isValid = sess.authenticate(request, un, pw);
888

    
889
        //if it is authernticate is true, store the session
890
        if (isValid) {
891
            HttpSession session = sess.getSessions();
892
            String id = session.getId();
893
            logMetacat.info("Store session id " + id
894
                    + "which has username" + session.getAttribute("username")
895
                    + " into hash in login method");
896
            sessionHash.put(id, session);
897
        }
898

    
899
        // format and transform the output
900
        if (qformat.equals("xml")) {
901
            response.setContentType("text/xml");
902
            out.println(sess.getMessage());
903
        } else {
904
            try {
905
                DBTransform trans = new DBTransform();
906
                response.setContentType("text/html");
907
                trans.transformXMLDocument(sess.getMessage(),
908
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
909
                        out, null);
910
            } catch (Exception e) {
911

    
912
                logMetacat.error(
913
                        "Error in MetaCatServlet.handleLoginAction: "
914
                                + e.getMessage());
915
            }
916
        }
917
    }
918

    
919
    /**
920
     * Handle the logout request. Close the connection.
921
     */
922
    private void handleLogoutAction(PrintWriter out, Hashtable params,
923
            HttpServletRequest request, HttpServletResponse response)
924
    {
925
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
926
        String qformat = "xml";
927
        if(params.get("qformat") != null){
928
            qformat = ((String[]) params.get("qformat"))[0];
929
        }
930

    
931
        // close the connection
932
        HttpSession sess = request.getSession(false);
933
        logMetacat.info("After get session in logout request");
934
        if (sess != null) {
935
            logMetacat.info("The session id " + sess.getId()
936
                    + " will be invalidate in logout action");
937
            logMetacat.info("The session contains user "
938
                    + sess.getAttribute("username")
939
                    + " will be invalidate in logout action");
940
            sess.invalidate();
941
        }
942

    
943
        // produce output
944
        StringBuffer output = new StringBuffer();
945
        output.append("<?xml version=\"1.0\"?>");
946
        output.append("<logout>");
947
        output.append("User logged out");
948
        output.append("</logout>");
949

    
950
        //format and transform the output
951
        if (qformat.equals("xml")) {
952
            response.setContentType("text/xml");
953
            out.println(output.toString());
954
        } else {
955
            try {
956
                DBTransform trans = new DBTransform();
957
                response.setContentType("text/html");
958
                trans.transformXMLDocument(output.toString(),
959
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
960
                        out, null);
961
            } catch (Exception e) {
962
                logMetacat.error(
963
                        "Error in MetaCatServlet.handleLogoutAction"
964
                                + e.getMessage());
965
            }
966
        }
967
    }
968

    
969
    // END OF LOGIN & LOGOUT SECTION
970

    
971
    // SQUERY & QUERY SECTION
972
    /**
973
     * Retreive the squery xml, execute it and display it
974
     *
975
     * @param out the output stream to the client
976
     * @param params the Hashtable of parameters that should be included in the
977
     *            squery.
978
     * @param response the response object linked to the client
979
     * @param conn the database connection
980
     */
981
    private void handleSQuery(PrintWriter out, Hashtable params,
982
            HttpServletResponse response, String user, String[] groups,
983
            String sessionid)
984
    {
985
        double startTime = System.currentTimeMillis() / 1000;
986
        DBQuery queryobj = new DBQuery();
987
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
988
        double outPutTime = System.currentTimeMillis() / 1000;
989
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
990
        logMetacat.info("Total search time for action 'squery': "
991
                + (outPutTime - startTime));
992
    }
993

    
994
    /**
995
     * Create the xml query, execute it and display the results.
996
     *
997
     * @param out the output stream to the client
998
     * @param params the Hashtable of parameters that should be included in the
999
     *            squery.
1000
     * @param response the response object linked to the client
1001
     */
1002
    private void handleQuery(PrintWriter out, Hashtable params,
1003
            HttpServletResponse response, String user, String[] groups,
1004
            String sessionid)
1005
    {
1006
        //create the query and run it
1007
        String xmlquery = DBQuery.createSQuery(params);
1008
        String[] queryArray = new String[1];
1009
        queryArray[0] = xmlquery;
1010
        params.put("query", queryArray);
1011
        double startTime = System.currentTimeMillis() / 1000;
1012
        DBQuery queryobj = new DBQuery();
1013
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
1014
        double outPutTime = System.currentTimeMillis() / 1000;
1015
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1016
        logMetacat.info("Total search time for action 'query': "
1017
                + (outPutTime - startTime));
1018

    
1019
        //handleSQuery(out, params, response,user, groups, sessionid);
1020
    }
1021

    
1022
    // END OF SQUERY & QUERY SECTION
1023

    
1024
    //Exoport section
1025
    /**
1026
     * Handle the "export" request of data package from Metacat in zip format
1027
     *
1028
     * @param params the Hashtable of HTTP request parameters
1029
     * @param response the HTTP response object linked to the client
1030
     * @param user the username sent the request
1031
     * @param groups the user's groupnames
1032
     */
1033
    private void handleExportAction(Hashtable params,
1034
            HttpServletResponse response,
1035
            String user, String[] groups, String passWord)
1036
    {
1037
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1038
        // Output stream
1039
        ServletOutputStream out = null;
1040
        // Zip output stream
1041
        ZipOutputStream zOut = null;
1042
        DBQuery queryObj = null;
1043

    
1044
        String[] docs = new String[10];
1045
        String docId = "";
1046

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

    
1083
        } catch (Exception e) {
1084
            try {
1085
                response.setContentType("text/xml"); //MIME type
1086
                // Send error message back
1087
                if (out != null) {
1088
                    PrintWriter pw = new PrintWriter(out);
1089
                    pw.println("<?xml version=\"1.0\"?>");
1090
                    pw.println("<error>");
1091
                    pw.println(e.getMessage());
1092
                    pw.println("</error>");
1093
                    // Close printwriter
1094
                    pw.close();
1095
                    // Close output stream
1096
                    out.close();
1097
                }
1098
                // Close zip output stream
1099
                if (zOut != null) {
1100
                    zOut.close();
1101
                }
1102
            } catch (IOException ioe) {
1103
                logMetacat.error("Problem with the servlet output "
1104
                        + "in MetacatServlet.handleExportAction: "
1105
                        + ioe.getMessage());
1106
            }
1107

    
1108
            logMetacat.error(
1109
                    "Error in MetacatServlet.handleExportAction: "
1110
                            + e.getMessage());
1111
            e.printStackTrace(System.out);
1112

    
1113
        }
1114

    
1115
    }
1116

    
1117
    /**
1118
     * In eml2 document, the xml can have inline data and data was stripped off
1119
     * and store in file system. This action can be used to read inline data
1120
     * only
1121
     *
1122
     * @param params the Hashtable of HTTP request parameters
1123
     * @param response the HTTP response object linked to the client
1124
     * @param user the username sent the request
1125
     * @param groups the user's groupnames
1126
     */
1127
    private void handleReadInlineDataAction(Hashtable params,
1128
            HttpServletRequest request, HttpServletResponse response,
1129
            String user, String passWord, String[] groups)
1130
    {
1131
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1132
        String[] docs = new String[10];
1133
        String inlineDataId = null;
1134
        String docId = "";
1135
        ServletOutputStream out = null;
1136

    
1137
        try {
1138
            // read the params
1139
            if (params.containsKey("inlinedataid")) {
1140
                docs = (String[]) params.get("inlinedataid");
1141
            }
1142
            // Get the docid
1143
            inlineDataId = docs[0];
1144
            // Make sure the client specify docid
1145
            if (inlineDataId == null || inlineDataId.equals("")) {
1146
                throw new Exception("You didn't specify requested inlinedataid"); }
1147

    
1148
            // check for permission
1149
            docId = MetaCatUtil
1150
                    .getDocIdWithoutRevFromInlineDataID(inlineDataId);
1151
            PermissionController controller = new PermissionController(docId);
1152
            // check top level read permission
1153
            if (!controller.hasPermission(user, groups,
1154
                    AccessControlInterface.READSTRING))
1155
            {
1156
                throw new Exception("User " + user
1157
                        + " doesn't have permission " + " to read document "
1158
                        + docId);
1159
            }
1160
            else
1161
            {
1162
              //check data access level
1163
              try
1164
              {
1165
                Hashtable unReadableInlineDataList =
1166
                    PermissionController.getUnReadableInlineDataIdList(docId,
1167
                    user, groups, false);
1168
                if (unReadableInlineDataList.containsValue(
1169
                          MetaCatUtil.getInlineDataIdWithoutRev(inlineDataId)))
1170
                {
1171
                  throw new Exception("User " + user
1172
                       + " doesn't have permission " + " to read inlinedata "
1173
                       + inlineDataId);
1174

    
1175
                }//if
1176
              }//try
1177
              catch (Exception e)
1178
              {
1179
                throw e;
1180
              }//catch
1181
            }//else
1182

    
1183
            // Get output stream
1184
            out = response.getOutputStream();
1185
            // read the inline data from the file
1186
            String inlinePath = MetaCatUtil.getOption("inlinedatafilepath");
1187
            File lineData = new File(inlinePath, inlineDataId);
1188
            FileInputStream input = new FileInputStream(lineData);
1189
            byte[] buffer = new byte[4 * 1024];
1190
            int bytes = input.read(buffer);
1191
            while (bytes != -1) {
1192
                out.write(buffer, 0, bytes);
1193
                bytes = input.read(buffer);
1194
            }
1195
            out.close();
1196

    
1197
            EventLog.getInstance().log(request.getRemoteAddr(), user,
1198
                    inlineDataId, "readinlinedata");
1199
        } catch (Exception e) {
1200
            try {
1201
                PrintWriter pw = null;
1202
                // Send error message back
1203
                if (out != null) {
1204
                    pw = new PrintWriter(out);
1205
                } else {
1206
                    pw = response.getWriter();
1207
                }
1208
                pw.println("<?xml version=\"1.0\"?>");
1209
                pw.println("<error>");
1210
                pw.println(e.getMessage());
1211
                pw.println("</error>");
1212
                // Close printwriter
1213
                pw.close();
1214
                // Close output stream if out is not null
1215
                if (out != null) {
1216
                    out.close();
1217
                }
1218
            } catch (IOException ioe) {
1219
                logMetacat.error("Problem with the servlet output "
1220
                        + "in MetacatServlet.handleExportAction: "
1221
                        + ioe.getMessage());
1222
            }
1223
            logMetacat.error(
1224
                    "Error in MetacatServlet.handleReadInlineDataAction: "
1225
                            + e.getMessage());
1226
        }
1227
    }
1228

    
1229
    /*
1230
     * Get the nodeid from xml_nodes for the inlinedataid
1231
     */
1232
    private long getInlineDataNodeId(String inLineDataId, String docId)
1233
            throws SQLException
1234
    {
1235
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1236
        long nodeId = 0;
1237
        String INLINE = "inline";
1238
        boolean hasRow;
1239
        PreparedStatement pStmt = null;
1240
        DBConnection conn = null;
1241
        int serialNumber = -1;
1242
        String sql = "SELECT nodeid FROM xml_nodes WHERE docid=? AND nodedata=? "
1243
                + "AND nodetype='TEXT' AND parentnodeid IN "
1244
                + "(SELECT nodeid FROM xml_nodes WHERE docid=? AND "
1245
                + "nodetype='ELEMENT' AND nodename='" + INLINE + "')";
1246

    
1247
        try {
1248
            //check out DBConnection
1249
            conn = DBConnectionPool
1250
                    .getDBConnection("AccessControlList.isAllowFirst");
1251
            serialNumber = conn.getCheckOutSerialNumber();
1252

    
1253
            pStmt = conn.prepareStatement(sql);
1254
            //bind value
1255
            pStmt.setString(1, docId);//docid
1256
            pStmt.setString(2, inLineDataId);//inlinedataid
1257
            pStmt.setString(3, docId);
1258
            // excute query
1259
            pStmt.execute();
1260
            ResultSet rs = pStmt.getResultSet();
1261
            hasRow = rs.next();
1262
            // get result
1263
            if (hasRow) {
1264
                nodeId = rs.getLong(1);
1265
            }//if
1266

    
1267
        } catch (SQLException e) {
1268
            throw e;
1269
        } finally {
1270
            try {
1271
                pStmt.close();
1272
            } finally {
1273
                DBConnectionPool.returnDBConnection(conn, serialNumber);
1274
            }
1275
        }
1276
        logMetacat.debug("The nodeid for inlinedataid " + inLineDataId
1277
                + " is: " + nodeId);
1278
        return nodeId;
1279
    }
1280

    
1281
    /**
1282
     * Handle the "read" request of metadata/data files from Metacat or any
1283
     * files from Internet; transformed metadata XML document into HTML
1284
     * presentation if requested; zip files when more than one were requested.
1285
     *
1286
     * @param params the Hashtable of HTTP request parameters
1287
     * @param request the HTTP request object linked to the client
1288
     * @param response the HTTP response object linked to the client
1289
     * @param user the username sent the request
1290
     * @param groups the user's groupnames
1291
     */
1292
    private void handleReadAction(Hashtable params, HttpServletRequest request,
1293
            HttpServletResponse response, String user, String passWord,
1294
            String[] groups)
1295
    {
1296
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1297
        ServletOutputStream out = null;
1298
        ZipOutputStream zout = null;
1299
        PrintWriter pw = null;
1300
        boolean zip = false;
1301
        boolean withInlineData = true;
1302

    
1303
        try {
1304
            String[] docs = new String[0];
1305
            String docid = "";
1306
            String qformat = "";
1307
            String abstrpath = null;
1308

    
1309
            // read the params
1310
            if (params.containsKey("docid")) {
1311
                docs = (String[]) params.get("docid");
1312
            }
1313
            if (params.containsKey("qformat")) {
1314
                qformat = ((String[]) params.get("qformat"))[0];
1315
            }
1316
            // the param for only metadata (eml)
1317
            // we don't support read a eml document without inline data now.
1318
            /*if (params.containsKey("inlinedata")) {
1319

    
1320
                String inlineData = ((String[]) params.get("inlinedata"))[0];
1321
                if (inlineData.equalsIgnoreCase("false")) {
1322
                    withInlineData = false;
1323
                }
1324
            }*/
1325
            if ((docs.length > 1) || qformat.equals("zip")) {
1326
                zip = true;
1327
                out = response.getOutputStream();
1328
                response.setContentType("application/zip"); //MIME type
1329
                zout = new ZipOutputStream(out);
1330
            }
1331
            // go through the list of docs to read
1332
            for (int i = 0; i < docs.length; i++) {
1333
                try {
1334

    
1335
                    URL murl = new URL(docs[i]);
1336
                    Hashtable murlQueryStr = MetaCatUtil.parseQuery(
1337
                            murl.getQuery());
1338
                    // case docid="http://.../?docid=aaa"
1339
                    // or docid="metacat://.../?docid=bbb"
1340
                    if (murlQueryStr.containsKey("docid")) {
1341
                        // get only docid, eliminate the rest
1342
                        docid = (String) murlQueryStr.get("docid");
1343
                        if (zip) {
1344
                            addDocToZip(request, docid, zout, user, groups);
1345
                        } else {
1346
                            readFromMetacat(request, response, docid, qformat,
1347
                                    abstrpath, user, groups, zip, zout,
1348
                                    withInlineData, params);
1349
                        }
1350

    
1351
                        // case docid="http://.../filename"
1352
                    } else {
1353
                        docid = docs[i];
1354
                        if (zip) {
1355
                            addDocToZip(request, docid, zout, user, groups);
1356
                        } else {
1357
                            readFromURLConnection(response, docid);
1358
                        }
1359
                    }
1360

    
1361
                } catch (MalformedURLException mue) {
1362
                    docid = docs[i];
1363
                    if (zip) {
1364
                        addDocToZip(request, docid, zout, user, groups);
1365
                    } else {
1366
                        readFromMetacat(request, response, docid, qformat,
1367
                                abstrpath, user, groups, zip, zout,
1368
                                withInlineData, params);
1369
                    }
1370
                }
1371
            }
1372

    
1373
            if (zip) {
1374
                zout.finish(); //terminate the zip file
1375
                zout.close(); //close the zip stream
1376
            }
1377

    
1378
        } catch (McdbDocNotFoundException notFoundE) {
1379
            // To handle doc not found exception
1380
            // the docid which didn't be found
1381
            String notFoundDocId = notFoundE.getUnfoundDocId();
1382
            String notFoundRevision = notFoundE.getUnfoundRevision();
1383
            logMetacat.warn("Missed id: " + notFoundDocId);
1384
            logMetacat.warn("Missed rev: " + notFoundRevision);
1385
            try {
1386
                // read docid from remote server
1387
                readFromRemoteMetaCat(response, notFoundDocId,
1388
                        notFoundRevision, user, passWord, out, zip, zout);
1389
                // Close zout outputstream
1390
                if (zout != null) {
1391
                    zout.close();
1392
                }
1393
                // close output stream
1394
                if (out != null) {
1395
                    out.close();
1396
                }
1397

    
1398
            } catch (Exception exc) {
1399
                logMetacat.error(
1400
                        "Erorr in MetacatServlet.hanldReadAction: "
1401
                                + exc.getMessage());
1402
                try {
1403
                    if (out != null) {
1404
                        response.setContentType("text/xml");
1405
                        // Send back error message by printWriter
1406
                        pw = new PrintWriter(out);
1407
                        pw.println("<?xml version=\"1.0\"?>");
1408
                        pw.println("<error>");
1409
                        pw.println(notFoundE.getMessage());
1410
                        pw.println("</error>");
1411
                        pw.close();
1412
                        out.close();
1413

    
1414
                    } else {
1415
                        response.setContentType("text/xml"); //MIME type
1416
                        // Send back error message if out = null
1417
                        if (pw == null) {
1418
                            // If pw is null, open the respnose
1419
                            pw = response.getWriter();
1420
                        }
1421
                        pw.println("<?xml version=\"1.0\"?>");
1422
                        pw.println("<error>");
1423
                        pw.println(notFoundE.getMessage());
1424
                        pw.println("</error>");
1425
                        pw.close();
1426
                    }
1427
                    // close zout
1428
                    if (zout != null) {
1429
                        zout.close();
1430
                    }
1431
                } catch (IOException ie) {
1432
                    logMetacat.error("Problem with the servlet output "
1433
                            + "in MetacatServlet.handleReadAction: "
1434
                            + ie.getMessage());
1435
                }
1436
            }
1437
        } catch (Exception e) {
1438
            try {
1439

    
1440
                if (out != null) {
1441
                    response.setContentType("text/xml"); //MIME type
1442
                    pw = new PrintWriter(out);
1443
                    pw.println("<?xml version=\"1.0\"?>");
1444
                    pw.println("<error>");
1445
                    pw.println(e.getMessage());
1446
                    pw.println("</error>");
1447
                    pw.close();
1448
                    out.close();
1449
                } else {
1450
                    response.setContentType("text/xml"); //MIME type
1451
                    // Send back error message if out = null
1452
                    if (pw == null) {
1453
                        pw = response.getWriter();
1454
                    }
1455
                    pw.println("<?xml version=\"1.0\"?>");
1456
                    pw.println("<error>");
1457
                    pw.println(e.getMessage());
1458
                    pw.println("</error>");
1459
                    pw.close();
1460

    
1461
                }
1462
                // Close zip output stream
1463
                if (zout != null) {
1464
                    zout.close();
1465
                }
1466

    
1467
            } catch (IOException ioe) {
1468
                logMetacat.error("Problem with the servlet output "
1469
                        + "in MetacatServlet.handleReadAction: "
1470
                        + ioe.getMessage());
1471
                ioe.printStackTrace(System.out);
1472

    
1473
            }
1474

    
1475
            logMetacat.error(
1476
                    "Error in MetacatServlet.handleReadAction: "
1477
                            + e.getMessage());
1478
            //e.printStackTrace(System.out);
1479
        }
1480
    }
1481

    
1482
    /** read metadata or data from Metacat
1483
     */
1484
    private void readFromMetacat(HttpServletRequest request,
1485
            HttpServletResponse response, String docid, String qformat,
1486
            String abstrpath, String user, String[] groups, boolean zip,
1487
            ZipOutputStream zout, boolean withInlineData, Hashtable params)
1488
            throws ClassNotFoundException, IOException, SQLException,
1489
            McdbException, Exception
1490
    {
1491
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1492
        try {
1493
            
1494
            // here is hack for handle docid=john.10(in order to tell mike.jim.10.1
1495
            // mike.jim.10, we require to provide entire docid with rev). But
1496
            // some old client they only provide docid without rev, so we need
1497
            // to handle this suituation. First we will check how many
1498
            // seperator here, if only one, we will append the rev in xml_documents
1499
            // to the id.
1500
            docid = appendRev(docid);
1501
         
1502
            DocumentImpl doc = new DocumentImpl(docid);
1503

    
1504
            //check the permission for read
1505
            if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1506
                Exception e = new Exception("User " + user
1507
                        + " does not have permission"
1508
                        + " to read the document with the docid " + docid);
1509

    
1510
                throw e;
1511
            }
1512

    
1513
            if (doc.getRootNodeID() == 0) {
1514
                // this is data file
1515
                String filepath = MetaCatUtil.getOption("datafilepath");
1516
                if (!filepath.endsWith("/")) {
1517
                    filepath += "/";
1518
                }
1519
                String filename = filepath + docid;
1520
                FileInputStream fin = null;
1521
                fin = new FileInputStream(filename);
1522

    
1523
                //MIME type
1524
                String contentType = getServletContext().getMimeType(filename);
1525
                if (contentType == null) {
1526
                    ContentTypeProvider provider = new ContentTypeProvider(
1527
                            docid);
1528
                    contentType = provider.getContentType();
1529
                    logMetacat.info("Final contenttype is: "
1530
                            + contentType);
1531
                }
1532

    
1533
                response.setContentType(contentType);
1534
                // if we decide to use "application/octet-stream" for all data
1535
                // returns
1536
                // response.setContentType("application/octet-stream");
1537

    
1538
                try {
1539

    
1540
                    ServletOutputStream out = response.getOutputStream();
1541
                    byte[] buf = new byte[4 * 1024]; // 4K buffer
1542
                    int b = fin.read(buf);
1543
                    while (b != -1) {
1544
                        out.write(buf, 0, b);
1545
                        b = fin.read(buf);
1546
                    }
1547
                } finally {
1548
                    if (fin != null) fin.close();
1549
                }
1550

    
1551
            } else {
1552
                // this is metadata doc
1553
                if (qformat.equals("xml") || qformat.equals("")) {
1554
                    // if equals "", that means no qformat is specified. hence
1555
                    // by default the document should be returned in xml format
1556
                    // set content type first
1557
                    response.setContentType("text/xml"); //MIME type
1558
                    PrintWriter out = response.getWriter();
1559
                    doc.toXml(out, user, groups, withInlineData);
1560
                } else {
1561
                    response.setContentType("text/html"); //MIME type
1562
                    PrintWriter out = response.getWriter();
1563

    
1564
                    // Look up the document type
1565
                    String doctype = doc.getDoctype();
1566
                    // Transform the document to the new doctype
1567
                    DBTransform dbt = new DBTransform();
1568
                    dbt.transformXMLDocument(doc.toString(user, groups,
1569
                            withInlineData), doctype, "-//W3C//HTML//EN",
1570
                            qformat, out, params);
1571
                }
1572

    
1573
            }
1574
            EventLog.getInstance().log(request.getRemoteAddr(), user,
1575
                    docid, "read");
1576
        } catch (Exception except) {
1577
            throw except;
1578
        }
1579
    }
1580

    
1581
    /**
1582
     * read data from URLConnection
1583
     */
1584
    private void readFromURLConnection(HttpServletResponse response,
1585
            String docid) throws IOException, MalformedURLException
1586
    {
1587
        ServletOutputStream out = response.getOutputStream();
1588
        String contentType = getServletContext().getMimeType(docid); //MIME
1589
                                                                     // type
1590
        if (contentType == null) {
1591
            if (docid.endsWith(".xml")) {
1592
                contentType = "text/xml";
1593
            } else if (docid.endsWith(".css")) {
1594
                contentType = "text/css";
1595
            } else if (docid.endsWith(".dtd")) {
1596
                contentType = "text/plain";
1597
            } else if (docid.endsWith(".xsd")) {
1598
                contentType = "text/xml";
1599
            } else if (docid.endsWith("/")) {
1600
                contentType = "text/html";
1601
            } else {
1602
                File f = new File(docid);
1603
                if (f.isDirectory()) {
1604
                    contentType = "text/html";
1605
                } else {
1606
                    contentType = "application/octet-stream";
1607
                }
1608
            }
1609
        }
1610
        response.setContentType(contentType);
1611
        // if we decide to use "application/octet-stream" for all data returns
1612
        // response.setContentType("application/octet-stream");
1613

    
1614
        // this is http url
1615
        URL url = new URL(docid);
1616
        BufferedInputStream bis = null;
1617
        try {
1618
            bis = new BufferedInputStream(url.openStream());
1619
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1620
            int b = bis.read(buf);
1621
            while (b != -1) {
1622
                out.write(buf, 0, b);
1623
                b = bis.read(buf);
1624
            }
1625
        } finally {
1626
            if (bis != null) bis.close();
1627
        }
1628

    
1629
    }
1630

    
1631
    /**
1632
     * read file/doc and write to ZipOutputStream
1633
     *
1634
     * @param docid
1635
     * @param zout
1636
     * @param user
1637
     * @param groups
1638
     * @throws ClassNotFoundException
1639
     * @throws IOException
1640
     * @throws SQLException
1641
     * @throws McdbException
1642
     * @throws Exception
1643
     */
1644
    private void addDocToZip(HttpServletRequest request, String docid,
1645
            ZipOutputStream zout, String user, String[] groups) throws
1646
            ClassNotFoundException, IOException, SQLException, McdbException,
1647
            Exception
1648
    {
1649
        byte[] bytestring = null;
1650
        ZipEntry zentry = null;
1651

    
1652
        try {
1653
            URL url = new URL(docid);
1654

    
1655
            // this http url; read from URLConnection; add to zip
1656
            zentry = new ZipEntry(docid);
1657
            zout.putNextEntry(zentry);
1658
            BufferedInputStream bis = null;
1659
            try {
1660
                bis = new BufferedInputStream(url.openStream());
1661
                byte[] buf = new byte[4 * 1024]; // 4K buffer
1662
                int b = bis.read(buf);
1663
                while (b != -1) {
1664
                    zout.write(buf, 0, b);
1665
                    b = bis.read(buf);
1666
                }
1667
            } finally {
1668
                if (bis != null) bis.close();
1669
            }
1670
            zout.closeEntry();
1671

    
1672
        } catch (MalformedURLException mue) {
1673

    
1674
            // this is metacat doc (data file or metadata doc)
1675
            try {
1676
                DocumentImpl doc = new DocumentImpl(docid);
1677

    
1678
                //check the permission for read
1679
                if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1680
                    Exception e = new Exception("User " + user
1681
                            + " does not have "
1682
                            + "permission to read the document with the docid "
1683
                            + docid);
1684
                    throw e;
1685
                }
1686

    
1687
                if (doc.getRootNodeID() == 0) {
1688
                    // this is data file; add file to zip
1689
                    String filepath = MetaCatUtil.getOption("datafilepath");
1690
                    if (!filepath.endsWith("/")) {
1691
                        filepath += "/";
1692
                    }
1693
                    String filename = filepath + docid;
1694
                    FileInputStream fin = null;
1695
                    fin = new FileInputStream(filename);
1696
                    try {
1697

    
1698
                        zentry = new ZipEntry(docid);
1699
                        zout.putNextEntry(zentry);
1700
                        byte[] buf = new byte[4 * 1024]; // 4K buffer
1701
                        int b = fin.read(buf);
1702
                        while (b != -1) {
1703
                            zout.write(buf, 0, b);
1704
                            b = fin.read(buf);
1705
                        }
1706
                    } finally {
1707
                        if (fin != null) fin.close();
1708
                    }
1709
                    zout.closeEntry();
1710

    
1711
                } else {
1712
                    // this is metadata doc; add doc to zip
1713
                    bytestring = doc.toString().getBytes();
1714
                    zentry = new ZipEntry(docid + ".xml");
1715
                    zentry.setSize(bytestring.length);
1716
                    zout.putNextEntry(zentry);
1717
                    zout.write(bytestring, 0, bytestring.length);
1718
                    zout.closeEntry();
1719
                }
1720
                EventLog.getInstance().log(request.getRemoteAddr(), user,
1721
                        docid, "read");
1722
            } catch (Exception except) {
1723
                throw except;
1724
            }
1725
        }
1726
    }
1727

    
1728
    /**
1729
     * If metacat couldn't find a data file or document locally, it will read
1730
     * this docid from its home server. This is for the replication feature
1731
     */
1732
    private void readFromRemoteMetaCat(HttpServletResponse response,
1733
            String docid, String rev, String user, String password,
1734
            ServletOutputStream out, boolean zip, ZipOutputStream zout)
1735
            throws Exception
1736
    {
1737
        // Create a object of RemoteDocument, "" is for zipEntryPath
1738
        RemoteDocument remoteDoc = new RemoteDocument(docid, rev, user,
1739
                password, "");
1740
        String docType = remoteDoc.getDocType();
1741
        // Only read data file
1742
        if (docType.equals("BIN")) {
1743
            // If it is zip format
1744
            if (zip) {
1745
                remoteDoc.readDocumentFromRemoteServerByZip(zout);
1746
            } else {
1747
                if (out == null) {
1748
                    out = response.getOutputStream();
1749
                }
1750
                response.setContentType("application/octet-stream");
1751
                remoteDoc.readDocumentFromRemoteServer(out);
1752
            }
1753
        } else {
1754
            throw new Exception("Docid: " + docid + "." + rev
1755
                    + " couldn't find");
1756
        }
1757
    }
1758

    
1759
    /**
1760
     * Handle the database putdocument request and write an XML document to the
1761
     * database connection
1762
     */
1763
    private void handleInsertOrUpdateAction(HttpServletRequest request,
1764
            HttpServletResponse response, PrintWriter out, Hashtable params,
1765
            String user, String[] groups)
1766
    {
1767
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1768
        DBConnection dbConn = null;
1769
        int serialNumber = -1;
1770

    
1771
        if(params.get("docid") == null){
1772
            out.println("<?xml version=\"1.0\"?>");
1773
            out.println("<error>");
1774
            out.println("Docid not specified");
1775
            out.println("</error>");
1776
            logMetacat.error("Docid not specified");
1777
            return;
1778
        }
1779
        
1780
        if(!MetaCatUtil.canInsertOrUpdate(user, groups)){
1781
        	out.println("<?xml version=\"1.0\"?>");
1782
            out.println("<error>");
1783
            out.println("User '" + user + "' not allowed to insert and update");
1784
            out.println("</error>");
1785
            logMetacat.error("User '" + user + "' not allowed to insert and update");
1786
            return;
1787
        }
1788

    
1789
        try {
1790
            // Get the document indicated
1791
            String[] doctext = (String[]) params.get("doctext");
1792
            String pub = null;
1793
            if (params.containsKey("public")) {
1794
                pub = ((String[]) params.get("public"))[0];
1795
            }
1796

    
1797
            StringReader dtd = null;
1798
            if (params.containsKey("dtdtext")) {
1799
                String[] dtdtext = (String[]) params.get("dtdtext");
1800
                try {
1801
                    if (!dtdtext[0].equals("")) {
1802
                        dtd = new StringReader(dtdtext[0]);
1803
                    }
1804
                } catch (NullPointerException npe) {
1805
                }
1806
            }
1807

    
1808
            if(doctext == null){
1809
                out.println("<?xml version=\"1.0\"?>");
1810
                out.println("<error>");
1811
                out.println("Document text not submitted");
1812
                out.println("</error>");
1813
                return;
1814
            }
1815

    
1816
            StringReader xml = new StringReader(doctext[0]);
1817
            boolean validate = false;
1818
            DocumentImplWrapper documentWrapper = null;
1819
            try {
1820
                // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ...
1821
                // >
1822
                // in order to decide whether to use validation parser
1823
                validate = needDTDValidation(xml);
1824
                if (validate) {
1825
                    // set a dtd base validation parser
1826
                    String rule = DocumentImpl.DTD;
1827
                    documentWrapper = new DocumentImplWrapper(rule, validate);
1828
                } else {
1829

    
1830
                    String namespace = findNamespace(xml);
1831
                    
1832
                	if (namespace != null) {
1833
                		if (namespace.compareTo(DocumentImpl.EML2_0_0NAMESPACE) == 0
1834
                				|| namespace.compareTo(
1835
                				DocumentImpl.EML2_0_1NAMESPACE) == 0) {
1836
                			// set eml2 base	 validation parser
1837
                			String rule = DocumentImpl.EML200;
1838
                			// using emlparser to check id validation
1839
                			EMLParser parser = new EMLParser(doctext[0]);
1840
                			documentWrapper = new DocumentImplWrapper(rule, true);
1841
                		} else if (namespace.compareTo(
1842
                                DocumentImpl.EML2_1_0NAMESPACE) == 0) {
1843
                			// set eml2 base validation parser
1844
                			String rule = DocumentImpl.EML210;
1845
                			// using emlparser to check id validation
1846
                			EMLParser parser = new EMLParser(doctext[0]);
1847
                			documentWrapper = new DocumentImplWrapper(rule, true);
1848
                		} else {
1849
                			// set schema base validation parser
1850
                			String rule = DocumentImpl.SCHEMA;
1851
                			documentWrapper = new DocumentImplWrapper(rule, true);
1852
                		}
1853
                	} else {
1854
                		documentWrapper = new DocumentImplWrapper("", false);
1855
                	}
1856
                }
1857

    
1858
                String[] action = (String[]) params.get("action");
1859
                String[] docid = (String[]) params.get("docid");
1860
                String newdocid = null;
1861

    
1862
                String doAction = null;
1863
                if (action[0].equals("insert")) {
1864
                    doAction = "INSERT";
1865
                } else if (action[0].equals("update")) {
1866
                    doAction = "UPDATE";
1867
                }
1868

    
1869
                try {
1870
                    // get a connection from the pool
1871
                    dbConn = DBConnectionPool
1872
                            .getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1873
                    serialNumber = dbConn.getCheckOutSerialNumber();
1874

    
1875
                    // write the document to the database
1876
                    try {
1877
                        String accNumber = docid[0];
1878
                        logMetacat.debug("" + doAction + " "
1879
                                + accNumber + "...");
1880
                        if (accNumber.equals("")) {
1881
                            accNumber = null;
1882
                        }
1883
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1884
                                doAction, accNumber, user, groups);
1885
                        EventLog.getInstance().log(request.getRemoteAddr(),
1886
                                user, accNumber, action[0]);
1887
                    } catch (NullPointerException npe) {
1888
                        newdocid = documentWrapper.write(dbConn, xml, pub, dtd,
1889
                                doAction, null, user, groups);
1890
                        EventLog.getInstance().log(request.getRemoteAddr(),
1891
                                user, "", action[0]);
1892
                    }
1893
                }
1894
                finally {
1895
                    // Return db connection
1896
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1897
                }
1898

    
1899
                // set content type and other response header fields first
1900
                //response.setContentType("text/xml");
1901
                out.println("<?xml version=\"1.0\"?>");
1902
                out.println("<success>");
1903
                out.println("<docid>" + newdocid + "</docid>");
1904
                out.println("</success>");
1905

    
1906
            } catch (NullPointerException npe) {
1907
                //response.setContentType("text/xml");
1908
                out.println("<?xml version=\"1.0\"?>");
1909
                out.println("<error>");
1910
                out.println(npe.getMessage());
1911
                out.println("</error>");
1912
                logMetacat.warn("Error in writing eml document to the database" + npe.getMessage());
1913
                npe.printStackTrace();
1914
            }
1915
        } catch (Exception e) {
1916
            //response.setContentType("text/xml");
1917
            out.println("<?xml version=\"1.0\"?>");
1918
            out.println("<error>");
1919
            out.println(e.getMessage());
1920
            out.println("</error>");
1921
            logMetacat.warn("Error in writing eml document to the database" + e.getMessage());
1922
            e.printStackTrace();
1923
        }
1924
    }
1925

    
1926
    /**
1927
     * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > in
1928
     * order to decide whether to use validation parser
1929
     */
1930
    private static boolean needDTDValidation(StringReader xmlreader)
1931
            throws IOException
1932
    {
1933
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1934
        StringBuffer cbuff = new StringBuffer();
1935
        java.util.Stack st = new java.util.Stack();
1936
        boolean validate = false;
1937
        int c;
1938
        int inx;
1939

    
1940
        // read from the stream until find the keywords
1941
        while ((st.empty() || st.size() < 4) && ((c = xmlreader.read()) != -1)) {
1942
            cbuff.append((char) c);
1943

    
1944
            // "<!DOCTYPE" keyword is found; put it in the stack
1945
            if ((inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1) {
1946
                cbuff = new StringBuffer();
1947
                st.push("<!DOCTYPE");
1948
            }
1949
            // "PUBLIC" keyword is found; put it in the stack
1950
            if ((inx = cbuff.toString().indexOf("PUBLIC")) != -1) {
1951
                cbuff = new StringBuffer();
1952
                st.push("PUBLIC");
1953
            }
1954
            // "SYSTEM" keyword is found; put it in the stack
1955
            if ((inx = cbuff.toString().indexOf("SYSTEM")) != -1) {
1956
                cbuff = new StringBuffer();
1957
                st.push("SYSTEM");
1958
            }
1959
            // ">" character is found; put it in the stack
1960
            // ">" is found twice: fisrt from <?xml ...?>
1961
            // and second from <!DOCTYPE ... >
1962
            if ((inx = cbuff.toString().indexOf(">")) != -1) {
1963
                cbuff = new StringBuffer();
1964
                st.push(">");
1965
            }
1966
        }
1967

    
1968
        // close the stream
1969
        xmlreader.reset();
1970

    
1971
        // check the stack whether it contains the keywords:
1972
        // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1973
        if (st.size() == 4) {
1974
            if (((String) st.pop()).equals(">")
1975
                    && (((String) st.peek()).equals("PUBLIC") | ((String) st
1976
                            .pop()).equals("SYSTEM"))
1977
                    && ((String) st.pop()).equals("<!DOCTYPE")) {
1978
                validate = true;
1979
            }
1980
        }
1981

    
1982
        logMetacat.info("Validation for dtd is " + validate);
1983
        return validate;
1984
    }
1985

    
1986
    // END OF INSERT/UPDATE SECTION
1987

    
1988
    /* check if the xml string contains key words to specify schema loocation */
1989
    private String findNamespace(StringReader xml) throws IOException
1990
    {
1991
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1992
        String namespace = null;
1993

    
1994
        String eml2_0_0NameSpace = DocumentImpl.EML2_0_0NAMESPACE;
1995
        String eml2_0_1NameSpace = DocumentImpl.EML2_0_1NAMESPACE;
1996
        String eml2_1_0NameSpace = DocumentImpl.EML2_1_0NAMESPACE;
1997

    
1998
        if (xml == null) {
1999
            logMetacat.debug("Validation for schema is "
2000
                    + namespace);
2001
            return namespace;
2002
        }
2003
        String targetLine = getSchemaLine(xml);
2004
		
2005
        if (targetLine != null) {
2006

    
2007
        	// find if the root element has prefix
2008
        	String prefix = getPrefix(targetLine);
2009
        	logMetacat.info("prefix is:" + prefix);
2010
        	int startIndex = 0;
2011
        	
2012
        	
2013
        	if(prefix != null)
2014
        	{
2015
        		// if prefix found then look for xmlns:prefix
2016
        		// element to find the ns 
2017
        		String namespaceWithPrefix = NAMESPACEKEYWORD 
2018
        					+ ":" + prefix;
2019
        		startIndex = targetLine.indexOf(namespaceWithPrefix);
2020
            	logMetacat.debug("namespaceWithPrefix is:" + namespaceWithPrefix+":");
2021
            	logMetacat.debug("startIndex is:" + startIndex);
2022
        		
2023
        	} else {
2024
        		// if prefix not found then look for xmlns
2025
        		// attribute to find the ns 
2026
        		startIndex = targetLine.indexOf(NAMESPACEKEYWORD);
2027
            	logMetacat.debug("startIndex is:" + startIndex);
2028
        	}
2029
        		
2030
            int start = 1;
2031
            int end = 1;
2032
            String namespaceString = null;
2033
            int count = 0;
2034
            if (startIndex != -1) {
2035
                for (int i = startIndex; i < targetLine.length(); i++) {
2036
                    if (targetLine.charAt(i) == '"') {
2037
                        count++;
2038
                    }
2039
                    if (targetLine.charAt(i) == '"' && count == 1) {
2040
                        start = i;
2041
                    }
2042
                    if (targetLine.charAt(i) == '"' && count == 2) {
2043
                        end = i;
2044
                        break;
2045
                    }
2046
                }
2047
            } 
2048
            // else: xmlns not found. namespace = null will be returned
2049

    
2050
         	logMetacat.debug("targetLine is " + targetLine);
2051
         	logMetacat.debug("start is " + end);
2052
         	logMetacat.debug("end is " + end);
2053
           
2054
            if(start < end){
2055
            	namespaceString = targetLine.substring(start + 1, end);
2056
            	logMetacat.debug("namespaceString is " + namespaceString);
2057
            }
2058
            logMetacat.debug("namespace in xml is: "
2059
                    + namespaceString);
2060
            if(namespaceString != null){
2061
            	if (namespaceString.indexOf(eml2_0_0NameSpace) != -1) {
2062
            		namespace = eml2_0_0NameSpace;
2063
            	} else if (namespaceString.indexOf(eml2_0_1NameSpace) != -1) {
2064
            		namespace = eml2_0_1NameSpace;
2065
            	} else if (namespaceString.indexOf(eml2_1_0NameSpace) != -1) {
2066
            		namespace = eml2_1_0NameSpace;
2067
            	} else {
2068
            		namespace = namespaceString;
2069
            	}
2070
            }
2071
        }
2072

    
2073
        logMetacat.debug("Validation for eml is " + namespace);
2074

    
2075
        return namespace;
2076

    
2077
    }
2078

    
2079
    private String getSchemaLine(StringReader xml) throws IOException
2080
    {
2081
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2082
        // find the line
2083
        String secondLine = null;
2084
        int count = 0;
2085
        int endIndex = 0;
2086
        int startIndex = 0;
2087
        final int TARGETNUM = 2;
2088
        StringBuffer buffer = new StringBuffer();
2089
        boolean comment = false;
2090
        char thirdPreviousCharacter = '?';
2091
        char secondPreviousCharacter = '?';
2092
        char previousCharacter = '?';
2093
        char currentCharacter = '?';
2094
        int tmp = xml.read();
2095
        while (tmp != -1) {
2096
            currentCharacter = (char)tmp;
2097
            //in a comment
2098
            if (currentCharacter == '-' && previousCharacter == '-'
2099
                    && secondPreviousCharacter == '!'
2100
                    && thirdPreviousCharacter == '<') {
2101
                comment = true;
2102
            }
2103
            //out of comment
2104
            if (comment && currentCharacter == '>' && previousCharacter == '-'
2105
                    && secondPreviousCharacter == '-') {
2106
                comment = false;
2107
            }
2108

    
2109
            //this is not comment
2110
            if (currentCharacter != '!' && previousCharacter == '<' && !comment) {
2111
                count++;
2112
            }
2113
            // get target line
2114
            if (count == TARGETNUM && currentCharacter != '>') {
2115
                buffer.append(currentCharacter);
2116
            }
2117
            if (count == TARGETNUM && currentCharacter == '>') {
2118
                break;
2119
            }
2120
            thirdPreviousCharacter = secondPreviousCharacter;
2121
            secondPreviousCharacter = previousCharacter;
2122
            previousCharacter = currentCharacter;
2123
            tmp = xml.read();
2124
        }
2125
        secondLine = buffer.toString();
2126
        logMetacat.debug("the second line string is: " + secondLine);
2127
        
2128
        xml.reset();
2129
        return secondLine;
2130
    }
2131

    
2132
    private String getPrefix(String schemaLine)
2133
    {
2134
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2135
        String prefix = null;
2136
        if(schemaLine.indexOf(" ") > 0){
2137
            String rootElement = "";
2138
            try {
2139
                rootElement = schemaLine.substring(0, schemaLine.indexOf(" "));
2140
            } catch (StringIndexOutOfBoundsException sioobe) {
2141
                rootElement = schemaLine;
2142
            }
2143

    
2144
            logMetacat.debug("rootElement:" + rootElement);
2145
        
2146
            if(rootElement.indexOf(":") > 0){
2147
                prefix = rootElement.substring(rootElement.indexOf(":") + 1,
2148
                    rootElement.length());
2149
            }
2150

    
2151
            if(prefix != null){
2152
                return prefix.trim();
2153
            }
2154
        }
2155
        return null;
2156
    }
2157

    
2158
    /**
2159
     * Handle the database delete request and delete an XML document from the
2160
     * database connection
2161
     */
2162
    private void handleDeleteAction(PrintWriter out, Hashtable params,
2163
            HttpServletRequest request, HttpServletResponse response,
2164
            String user, String[] groups)
2165
    {
2166
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2167
        String[] docid = (String[]) params.get("docid");
2168

    
2169
        if(docid == null){
2170
          response.setContentType("text/xml");
2171
          out.println("<?xml version=\"1.0\"?>");
2172
          out.println("<error>");
2173
          out.println("Docid not specified.");
2174
          out.println("</error>");
2175
          logMetacat.error("Docid not specified for the document to be deleted.");
2176
        } else {
2177

    
2178
            // delete the document from the database
2179
            try {
2180

    
2181
                try {
2182
                    // null means notify server is null
2183
                    DocumentImpl.delete(docid[0], user, groups, null);
2184
                    EventLog.getInstance().log(request.getRemoteAddr(),
2185
                                               user, docid[0], "delete");
2186
                    response.setContentType("text/xml");
2187
                    out.println("<?xml version=\"1.0\"?>");
2188
                    out.println("<success>");
2189
                    out.println("Document deleted.");
2190
                    out.println("</success>");
2191
                    logMetacat.info("Document deleted.");
2192
                }
2193
                catch (AccessionNumberException ane) {
2194
                    response.setContentType("text/xml");
2195
                    out.println("<?xml version=\"1.0\"?>");
2196
                    out.println("<error>");
2197
                    //out.println("Error deleting document!!!");
2198
                    out.println(ane.getMessage());
2199
                    out.println("</error>");
2200
                    logMetacat.error("Document could not be deleted: " 
2201
                    		+ ane.getMessage());
2202
                }
2203
            }
2204
            catch (Exception e) {
2205
                response.setContentType("text/xml");
2206
                out.println("<?xml version=\"1.0\"?>");
2207
                out.println("<error>");
2208
                out.println(e.getMessage());
2209
                out.println("</error>");
2210
                logMetacat.error("Document could not be deleted: " 
2211
                		+ e.getMessage());
2212
            }
2213
        }
2214
    }
2215

    
2216
    /**
2217
     * Handle the validation request and return the results to the requestor
2218
     */
2219
    private void handleValidateAction(PrintWriter out, Hashtable params)
2220
    {
2221

    
2222
        // Get the document indicated
2223
        String valtext = null;
2224
        DBConnection dbConn = null;
2225
        int serialNumber = -1;
2226

    
2227
        try {
2228
            valtext = ((String[]) params.get("valtext"))[0];
2229
        } catch (Exception nullpe) {
2230

    
2231
            String docid = null;
2232
            try {
2233
                // Find the document id number
2234
                docid = ((String[]) params.get("docid"))[0];
2235

    
2236
                // Get the document indicated from the db
2237
                DocumentImpl xmldoc = new DocumentImpl(docid);
2238
                valtext = xmldoc.toString();
2239

    
2240
            } catch (NullPointerException npe) {
2241

    
2242
                out.println("<error>Error getting document ID: " + docid
2243
                        + "</error>");
2244
                //if ( conn != null ) { util.returnConnection(conn); }
2245
                return;
2246
            } catch (Exception e) {
2247

    
2248
                out.println(e.getMessage());
2249
            }
2250
        }
2251

    
2252
        try {
2253
            // get a connection from the pool
2254
            dbConn = DBConnectionPool
2255
                    .getDBConnection("MetaCatServlet.handleValidateAction");
2256
            serialNumber = dbConn.getCheckOutSerialNumber();
2257
            DBValidate valobj = new DBValidate(dbConn);
2258
            boolean valid = valobj.validateString(valtext);
2259

    
2260
            // set content type and other response header fields first
2261

    
2262
            out.println(valobj.returnErrors());
2263

    
2264
        } catch (NullPointerException npe2) {
2265
            // set content type and other response header fields first
2266

    
2267
            out.println("<error>Error validating document.</error>");
2268
        } catch (Exception e) {
2269

    
2270
            out.println(e.getMessage());
2271
        } finally {
2272
            // Return db connection
2273
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2274
        }
2275
    }
2276

    
2277
    /**
2278
     * Handle "getrevsionanddoctype" action Given a docid, return it's current
2279
     * revision and doctype from data base The output is String look like
2280
     * "rev;doctype"
2281
     */
2282
    private void handleGetRevisionAndDocTypeAction(PrintWriter out,
2283
            Hashtable params)
2284
    {
2285
        // To store doc parameter
2286
        String[] docs = new String[10];
2287
        // Store a single doc id
2288
        String givenDocId = null;
2289
        // Get docid from parameters
2290
        if (params.containsKey("docid")) {
2291
            docs = (String[]) params.get("docid");
2292
        }
2293
        // Get first docid form string array
2294
        givenDocId = docs[0];
2295

    
2296
        try {
2297
            // Make sure there is a docid
2298
            if (givenDocId == null || givenDocId.equals("")) { throw new Exception(
2299
                    "User didn't specify docid!"); }//if
2300

    
2301
            // Create a DBUtil object
2302
            DBUtil dbutil = new DBUtil();
2303
            // Get a rev and doctype
2304
            String revAndDocType = dbutil
2305
                    .getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
2306
            out.println(revAndDocType);
2307

    
2308
        } catch (Exception e) {
2309
            // Handle exception
2310
            out.println("<?xml version=\"1.0\"?>");
2311
            out.println("<error>");
2312
            out.println(e.getMessage());
2313
            out.println("</error>");
2314
        }
2315

    
2316
    }
2317

    
2318
    /**
2319
     * Handle "getaccesscontrol" action. Read Access Control List from db
2320
     * connection in XML format
2321
     */
2322
    private void handleGetAccessControlAction(PrintWriter out,
2323
            Hashtable params, HttpServletResponse response, String username,
2324
            String[] groupnames)
2325
    {
2326
        DBConnection dbConn = null;
2327
        int serialNumber = -1;
2328
        String docid = ((String[]) params.get("docid"))[0];
2329

    
2330
        try {
2331

    
2332
            // get connection from the pool
2333
            dbConn = DBConnectionPool
2334
                    .getDBConnection("MetaCatServlet.handleGetAccessControlAction");
2335
            serialNumber = dbConn.getCheckOutSerialNumber();
2336
            AccessControlList aclobj = new AccessControlList(dbConn);
2337
            String acltext = aclobj.getACL(docid, username, groupnames);
2338
            out.println(acltext);
2339

    
2340
        } catch (Exception e) {
2341
            out.println("<?xml version=\"1.0\"?>");
2342
            out.println("<error>");
2343
            out.println(e.getMessage());
2344
            out.println("</error>");
2345
        } finally {
2346
            // Retrun db connection to pool
2347
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2348
        }
2349
    }
2350

    
2351
    /**
2352
     * Handle the "getprincipals" action. Read all principals from
2353
     * authentication scheme in XML format
2354
     */
2355
    private void handleGetPrincipalsAction(PrintWriter out, String user,
2356
            String password)
2357
    {
2358
        try {
2359
            AuthSession auth = new AuthSession();
2360
            String principals = auth.getPrincipals(user, password);
2361
            out.println(principals);
2362

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

    
2371
    /**
2372
     * Handle "getdoctypes" action. Read all doctypes from db connection in XML
2373
     * format
2374
     */
2375
    private void handleGetDoctypesAction(PrintWriter out, Hashtable params,
2376
            HttpServletResponse response)
2377
    {
2378
        try {
2379
            DBUtil dbutil = new DBUtil();
2380
            String doctypes = dbutil.readDoctypes();
2381
            out.println(doctypes);
2382
        } catch (Exception e) {
2383
            out.println("<?xml version=\"1.0\"?>");
2384
            out.println("<error>");
2385
            out.println(e.getMessage());
2386
            out.println("</error>");
2387
        }
2388
    }
2389

    
2390
    /**
2391
     * Handle the "getdtdschema" action. Read DTD or Schema file for a given
2392
     * doctype from Metacat catalog system
2393
     */
2394
    private void handleGetDTDSchemaAction(PrintWriter out, Hashtable params,
2395
            HttpServletResponse response)
2396
    {
2397

    
2398
        String doctype = null;
2399
        String[] doctypeArr = (String[]) params.get("doctype");
2400

    
2401
        // get only the first doctype specified in the list of doctypes
2402
        // it could be done for all doctypes in that list
2403
        if (doctypeArr != null) {
2404
            doctype = ((String[]) params.get("doctype"))[0];
2405
        }
2406

    
2407
        try {
2408
            DBUtil dbutil = new DBUtil();
2409
            String dtdschema = dbutil.readDTDSchema(doctype);
2410
            out.println(dtdschema);
2411

    
2412
        } catch (Exception e) {
2413
            out.println("<?xml version=\"1.0\"?>");
2414
            out.println("<error>");
2415
            out.println(e.getMessage());
2416
            out.println("</error>");
2417
        }
2418

    
2419
    }
2420

    
2421
    /**
2422
     * Handle the "getlastdocid" action. Get the latest docid with rev number
2423
     * from db connection in XML format
2424
     */
2425
    private void handleGetMaxDocidAction(PrintWriter out, Hashtable params,
2426
            HttpServletResponse response)
2427
    {
2428

    
2429
        String scope = ((String[]) params.get("scope"))[0];
2430
        if (scope == null) {
2431
            scope = ((String[]) params.get("username"))[0];
2432
        }
2433

    
2434
        try {
2435

    
2436
            DBUtil dbutil = new DBUtil();
2437
            String lastDocid = dbutil.getMaxDocid(scope);
2438
            out.println("<?xml version=\"1.0\"?>");
2439
            out.println("<lastDocid>");
2440
            out.println("  <scope>" + scope + "</scope>");
2441
            out.println("  <docid>" + lastDocid + "</docid>");
2442
            out.println("</lastDocid>");
2443

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

    
2452
    /**
2453
     * Print a report from the event log based on filter parameters passed in
2454
     * from the web.
2455
     *
2456
     * @param params the parameters from the web request
2457
     * @param request the http request object for getting request details
2458
     * @param response the http response object for writing output
2459
     */
2460
    private void handleGetLogAction(Hashtable params, HttpServletRequest request,
2461
            HttpServletResponse response, String username, String[] groups)
2462
    {
2463
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2464
        try {
2465
            response.setContentType("text/xml");
2466
            PrintWriter out = response.getWriter();
2467

    
2468
            // Check that the user is authenticated as an administrator account
2469
            if (!MetaCatUtil.isAdministrator(username, groups)) {
2470
                out.print("<error>");
2471
                out.print("The user \"" + username +
2472
                        "\" is not authorized for this action.");
2473
                out.print("</error>");
2474
                return;
2475
            }
2476

    
2477
            // Get all of the parameters in the correct formats
2478
            String[] ipAddress = (String[])params.get("ipaddress");
2479
            String[] principal = (String[])params.get("principal");
2480
            String[] docid = (String[])params.get("docid");
2481
            String[] event = (String[])params.get("event");
2482
            String[] startArray = (String[]) params.get("start");
2483
            String[] endArray = (String[]) params.get("end");
2484
            String start = null;
2485
            String end = null;
2486
            if (startArray != null) {
2487
                start = startArray[0];
2488
            }
2489
            if (endArray != null) {
2490
                end = endArray[0];
2491
            }
2492
            Timestamp startDate = null;
2493
            Timestamp endDate = null;
2494
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
2495
            try {
2496
                if (start != null) {
2497
                    startDate = new Timestamp((format.parse(start)).getTime());
2498
                }
2499
                if (end != null) {
2500
                    endDate = new Timestamp((format.parse(end)).getTime());
2501
                }
2502
            } catch (ParseException e) {
2503
                System.out.println("Failed to created Timestamp from input.");
2504
            }
2505

    
2506
            // Request the report by passing the filter parameters
2507
            out.println(EventLog.getInstance().getReport(ipAddress, principal,
2508
                    docid, event, startDate, endDate));
2509
            out.close();
2510
        } catch (IOException e) {
2511
            logMetacat.error(
2512
                    "Could not open http response for writing: " + e.getMessage());
2513
        }
2514
    }
2515

    
2516
    /**
2517
     * Rebuild the index for one or more documents. If the docid parameter is
2518
     * provided, rebuild for just that one document or list of documents. If
2519
     * not, then rebuild the index for all documents in the xml_documents
2520
     * table.
2521
     *
2522
     * @param params the parameters from the web request
2523
     * @param request the http request object for getting request details
2524
     * @param response the http response object for writing output
2525
     * @param username the username of the authenticated user
2526
     */
2527
    private void handleBuildIndexAction(Hashtable params,
2528
            HttpServletRequest request, HttpServletResponse response,
2529
            String username, String[] groups)
2530
    {
2531
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2532
        
2533
        // Get all of the parameters in the correct formats
2534
        String[] docid = (String[])params.get("docid");
2535

    
2536
        // Rebuild the indices for appropriate documents
2537
        try {
2538
            response.setContentType("text/xml");
2539
            PrintWriter out = response.getWriter();
2540

    
2541
            // Check that the user is authenticated as an administrator account
2542
            if (!MetaCatUtil.isAdministrator(username, groups)) {
2543
                out.print("<error>");
2544
                out.print("The user \"" + username +
2545
                        "\" is not authorized for this action.");
2546
                out.print("</error>");
2547
                return;
2548
            }
2549

    
2550
            // Process the documents
2551
            out.println("<success>");
2552
            if (docid == null || docid.length == 0) {
2553
                // Process all of the documents
2554
                try {
2555
                    Vector documents = getDocumentList();
2556
                    Iterator it = documents.iterator();
2557
                    while (it.hasNext()) {
2558
                        String id = (String) it.next();
2559
                        buildDocumentIndex(id, out);
2560
                    }
2561
                } catch (SQLException se) {
2562
                    out.print("<error>");
2563
                    out.print(se.getMessage());
2564
                    out.println("</error>");
2565
                }
2566
            } else {
2567
                // Only process the requested documents
2568
                for (int i = 0; i < docid.length; i++) {
2569
                    buildDocumentIndex(docid[i], out);
2570
                }
2571
            }
2572
            out.println("</success>");
2573
            out.close();
2574
        } catch (IOException e) {
2575
            logMetacat.error(
2576
                    "Could not open http response for writing: "
2577
                    + e.getMessage());
2578
        }
2579
    }
2580

    
2581
    /**
2582
     * Build the index for one document by reading the document and
2583
     * calling its buildIndex() method.
2584
     *
2585
     * @param docid the document (with revision) to rebuild
2586
     * @param out the PrintWriter to which output is printed
2587
     */
2588
    private void buildDocumentIndex(String docid, PrintWriter out)
2589
    {
2590
        try {
2591
            DocumentImpl doc = new DocumentImpl(docid, false);
2592
            doc.buildIndex();
2593
            out.print("<docid>" + docid);
2594
            out.println("</docid>");
2595
        } catch (McdbException me) {
2596
            out.print("<error>");
2597
            out.print(me.getMessage());
2598
            out.println("</error>");
2599
        }
2600
    }
2601

    
2602
    /**
2603
     * Handle documents passed to metacat that are encoded using the
2604
     * "multipart/form-data" mime type. This is typically used for uploading
2605
     * data files which may be binary and large.
2606
     */
2607
    private void handleMultipartForm(HttpServletRequest request,
2608
            HttpServletResponse response)
2609
    {
2610
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2611
        PrintWriter out = null;
2612
        String action = null;
2613

    
2614
        // Parse the multipart form, and save the parameters in a Hashtable and
2615
        // save the FileParts in a hashtable
2616

    
2617
        Hashtable params = new Hashtable();
2618
        Hashtable fileList = new Hashtable();
2619
        int sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit")))
2620
                .intValue();
2621
        logMetacat.info(
2622
                "The size limit of uploaded data files is: " + sizeLimit);
2623

    
2624
        try {
2625
            MultipartParser mp = new MultipartParser(request,
2626
                    sizeLimit * 1024 * 1024);
2627
            Part part;
2628
            while ((part = mp.readNextPart()) != null) {
2629
                String name = part.getName();
2630

    
2631
                if (part.isParam()) {
2632
                    // it's a parameter part
2633
                    ParamPart paramPart = (ParamPart) part;
2634
                    String value = paramPart.getStringValue();
2635
                    params.put(name, value);
2636
                    if (name.equals("action")) {
2637
                        action = value;
2638
                    }
2639
                } else if (part.isFile()) {
2640
                    // it's a file part
2641
                    FilePart filePart = (FilePart) part;
2642
                    fileList.put(name, filePart);
2643

    
2644
                    // Stop once the first file part is found, otherwise going
2645
                    // onto the
2646
                    // next part prevents access to the file contents. So...for
2647
                    // upload
2648
                    // to work, the datafile must be the last part
2649
                    break;
2650
                }
2651
            }
2652
        } catch (IOException ioe) {
2653
            try {
2654
                out = response.getWriter();
2655
            } catch (IOException ioe2) {
2656
                logMetacat.fatal("Fatal Error: couldn't get response output stream.");
2657
            }
2658
            out.println("<?xml version=\"1.0\"?>");
2659
            out.println("<error>");
2660
            out.println("Error: problem reading multipart data.");
2661
            out.println("</error>");
2662
        }
2663

    
2664
        // Get the session information
2665
        String username = null;
2666
        String password = null;
2667
        String[] groupnames = null;
2668
        String sess_id = null;
2669

    
2670
        // be aware of session expiration on every request
2671
        HttpSession sess = request.getSession(true);
2672
        if (sess.isNew()) {
2673
            // session expired or has not been stored b/w user requests
2674
            username = "public";
2675
            sess.setAttribute("username", username);
2676
        } else {
2677
            username = (String) sess.getAttribute("username");
2678
            password = (String) sess.getAttribute("password");
2679
            groupnames = (String[]) sess.getAttribute("groupnames");
2680
            try {
2681
                sess_id = (String) sess.getId();
2682
            } catch (IllegalStateException ise) {
2683
                System.out
2684
                        .println("error in  handleMultipartForm: this shouldn't "
2685
                                + "happen: the session should be valid: "
2686
                                + ise.getMessage());
2687
            }
2688
        }
2689

    
2690
        // Get the out stream
2691
        try {
2692
            out = response.getWriter();
2693
        } catch (IOException ioe2) {
2694
            logMetacat.error("Fatal Error: couldn't get response "
2695
                    + "output stream.");
2696
        }
2697

    
2698
        if (action.equals("upload")) {
2699
            if (username != null && !username.equals("public")) {
2700
                handleUploadAction(request, out, params, fileList, username,
2701
                        groupnames);
2702
            } else {
2703

    
2704
                out.println("<?xml version=\"1.0\"?>");
2705
                out.println("<error>");
2706
                out.println("Permission denied for " + action);
2707
                out.println("</error>");
2708
            }
2709
        } else {
2710
            /*
2711
             * try { out = response.getWriter(); } catch (IOException ioe2) {
2712
             * System.err.println("Fatal Error: couldn't get response output
2713
             * stream.");
2714
             */
2715
            out.println("<?xml version=\"1.0\"?>");
2716
            out.println("<error>");
2717
            out.println(
2718
                    "Error: action not registered.  Please report this error.");
2719
            out.println("</error>");
2720
        }
2721
        out.close();
2722
    }
2723

    
2724
    /**
2725
     * Handle the upload action by saving the attached file to disk and
2726
     * registering it in the Metacat db
2727
     */
2728
    private void handleUploadAction(HttpServletRequest request,
2729
            PrintWriter out, Hashtable params, Hashtable fileList,
2730
            String username, String[] groupnames)
2731
    {
2732
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2733
        //PrintWriter out = null;
2734
        //Connection conn = null;
2735
        String action = null;
2736
        String docid = null;
2737

    
2738
        /*
2739
         * response.setContentType("text/xml"); try { out =
2740
         * response.getWriter(); } catch (IOException ioe2) {
2741
         * System.err.println("Fatal Error: couldn't get response output
2742
         * stream.");
2743
         */
2744

    
2745
        if (params.containsKey("docid")) {
2746
            docid = (String) params.get("docid");
2747
        }
2748

    
2749
        // Make sure we have a docid and datafile
2750
        if (docid != null && fileList.containsKey("datafile")) {
2751
            logMetacat.info("Uploading data docid: " + docid);
2752
            // Get a reference to the file part of the form
2753
            FilePart filePart = (FilePart) fileList.get("datafile");
2754
            String fileName = filePart.getFileName();
2755
            logMetacat.info("Uploading filename: " + fileName);
2756
            // Check if the right file existed in the uploaded data
2757
            if (fileName != null) {
2758

    
2759
                try {
2760
                    //logMetacat.info("Upload datafile " + docid
2761
                    // +"...", 10);
2762
                    //If document get lock data file grant
2763
                    if (DocumentImpl.getDataFileLockGrant(docid)) {
2764
                        // Save the data file to disk using "docid" as the name
2765
                        String datafilepath = MetaCatUtil.getOption("datafilepath");
2766
                        File dataDirectory = new File(datafilepath);
2767
                        dataDirectory.mkdirs();
2768
                        File newFile = null;
2769
                        long size = 0;
2770
                        try
2771
                        {
2772
                          newFile = new File(dataDirectory, docid);
2773
                          size = filePart.writeTo(newFile);
2774
                        
2775
//                        register the file in the database (which generates
2776
                          // an exception
2777
                          //if the docid is not acceptable or other untoward
2778
                          // things happen
2779
                          DocumentImpl.registerDocument(fileName, "BIN", docid,
2780
                                username, groupnames);
2781
                        }
2782
                        catch (Exception ee)
2783
                        {
2784
                           //detelte the file to create
2785
                            newFile.delete();
2786
                            throw ee;
2787
                        }
2788

    
2789
                        EventLog.getInstance().log(request.getRemoteAddr(),
2790
                                username, docid, "upload");
2791
                        // Force replication this data file
2792
                        // To data file, "insert" and update is same
2793
                        // The fourth parameter is null. Because it is
2794
                        // notification server
2795
                        // and this method is in MetaCatServerlet. It is
2796
                        // original command,
2797
                        // not get force replication info from another metacat
2798
                        ForceReplicationHandler frh = new ForceReplicationHandler(
2799
                                docid, "insert", false, null);
2800

    
2801
                        // set content type and other response header fields
2802
                        // first
2803
                        out.println("<?xml version=\"1.0\"?>");
2804
                        out.println("<success>");
2805
                        out.println("<docid>" + docid + "</docid>");
2806
                        out.println("<size>" + size + "</size>");
2807
                        out.println("</success>");
2808
                    }
2809

    
2810
                } catch (Exception e) {
2811
                    
2812
                    out.println("<?xml version=\"1.0\"?>");
2813
                    out.println("<error>");
2814
                    out.println(e.getMessage());
2815
                    out.println("</error>");
2816
                }
2817
            } else {
2818
                // the field did not contain a file
2819
                out.println("<?xml version=\"1.0\"?>");
2820
                out.println("<error>");
2821
                out.println("The uploaded data did not contain a valid file.");
2822
                out.println("</error>");
2823
            }
2824
        } else {
2825
            // Error bcse docid missing or file missing
2826
            out.println("<?xml version=\"1.0\"?>");
2827
            out.println("<error>");
2828
            out.println("The uploaded data did not contain a valid docid "
2829
                    + "or valid file.");
2830
            out.println("</error>");
2831
        }
2832
    }
2833

    
2834
    /*
2835
     * A method to handle set access action
2836
     */
2837
    private void handleSetAccessAction(PrintWriter out, Hashtable params,
2838
            String username)
2839
    {
2840
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2841
        String[] docList = null;
2842
        String[] principalList = null;
2843
        String[] permissionList = null;
2844
        String[] permTypeList = null;
2845
        String[] permOrderList = null;
2846
        String permission = null;
2847
        String permType = null;
2848
        String permOrder = null;
2849
        Vector errorList = new Vector();
2850
        String error = null;
2851
        Vector successList = new Vector();
2852
        String success = null;
2853

    
2854
        // Get parameters
2855
        if (params.containsKey("docid")) {
2856
            docList = (String[]) params.get("docid");
2857
        }
2858
        if (params.containsKey("principal")) {
2859
            principalList = (String[]) params.get("principal");
2860
        }
2861
        if (params.containsKey("permission")) {
2862
            permissionList = (String[]) params.get("permission");
2863

    
2864
        }
2865
        if (params.containsKey("permType")) {
2866
            permTypeList = (String[]) params.get("permType");
2867

    
2868
        }
2869
        if (params.containsKey("permOrder")) {
2870
            permOrderList = (String[]) params.get("permOrder");
2871

    
2872
        }
2873

    
2874
        // Make sure the parameter is not null
2875
        if (docList == null || principalList == null || permTypeList == null
2876
                || permissionList == null) {
2877
            error = "Please check your parameter list, it should look like: "
2878
                    + "?action=setaccess&docid=pipeline.1.1&principal=public"
2879
                    + "&permission=read&permType=allow&permOrder=allowFirst";
2880
            errorList.addElement(error);
2881
            outputResponse(successList, errorList, out);
2882
            return;
2883
        }
2884

    
2885
        // Only select first element for permission, type and order
2886
        permission = permissionList[0];
2887
        permType = permTypeList[0];
2888
        if (permOrderList != null) {
2889
            permOrder = permOrderList[0];
2890
        }
2891

    
2892
        // Get package doctype set
2893
        Vector packageSet = MetaCatUtil.getOptionList(MetaCatUtil
2894
                .getOption("packagedoctypeset"));
2895
        //debug
2896
        if (packageSet != null) {
2897
            for (int i = 0; i < packageSet.size(); i++) {
2898
                logMetacat.debug("doctype in package set: "
2899
                        + (String) packageSet.elementAt(i));
2900
            }
2901
        }
2902

    
2903
        // handle every accessionNumber
2904
        for (int i = 0; i < docList.length; i++) {
2905
            String accessionNumber = docList[i];
2906
            String owner = null;
2907
            String publicId = null;
2908
            // Get document owner and public id
2909
            try {
2910
                owner = getFieldValueForDoc(accessionNumber, "user_owner");
2911
                publicId = getFieldValueForDoc(accessionNumber, "doctype");
2912
            } catch (Exception e) {
2913
                logMetacat.error("Error in handleSetAccessAction: "
2914
                        + e.getMessage());
2915
                error = "Error in set access control for document - "
2916
                        + accessionNumber + e.getMessage();
2917
                errorList.addElement(error);
2918
                continue;
2919
            }
2920
            //check if user is the owner. Only owner can do owner
2921
            if (username == null || owner == null || !username.equals(owner)) {
2922
                error = "User - " + username
2923
                        + " does not have permission to set "
2924
                        + "access control for docid - " + accessionNumber;
2925
                errorList.addElement(error);
2926
                continue;
2927
            }
2928

    
2929
            // If docid publicid is BIN data file or other beta4, 6 package
2930
            // document
2931
            // we could not do set access control. Because we don't want
2932
            // inconsistent
2933
            // to its access docuemnt
2934
            if (publicId != null && packageSet != null
2935
                    && packageSet.contains(publicId)) {
2936
                error = "Could not set access control to document "
2937
                        + accessionNumber
2938
                        + "because it is in a pakcage and it has a access file for it";
2939
                errorList.addElement(error);
2940
                continue;
2941
            }
2942

    
2943
            // for every principle
2944
            for (int j = 0; j < principalList.length; j++) {
2945
                String principal = principalList[j];
2946
                try {
2947
                    //insert permission
2948
                    AccessControlForSingleFile accessControl = new AccessControlForSingleFile(
2949
                            accessionNumber, principal, permission, permType,
2950
                            permOrder);
2951
                    accessControl.insertPermissions();
2952
                    success = "Set access control to document "
2953
                            + accessionNumber + " successfully";
2954
                    successList.addElement(success);
2955
                } catch (Exception ee) {
2956
                    logMetacat.error(
2957
                            "Erorr in handleSetAccessAction2: "
2958
                                    + ee.getMessage());
2959
                    error = "Faild to set access control for document "
2960
                            + accessionNumber + " because " + ee.getMessage();
2961
                    errorList.addElement(error);
2962
                    continue;
2963
                }
2964
            }
2965
        }
2966
        outputResponse(successList, errorList, out);
2967
    }
2968

    
2969
    /*
2970
     * A method try to determin a docid's public id, if couldn't find null will
2971
     * be returned.
2972
     */
2973
    private String getFieldValueForDoc(String accessionNumber, String fieldName)
2974
            throws Exception
2975
    {
2976
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2977
        if (accessionNumber == null || accessionNumber.equals("")
2978
                || fieldName == null || fieldName.equals("")) { throw new Exception(
2979
                "Docid or field name was not specified"); }
2980

    
2981
        PreparedStatement pstmt = null;
2982
        ResultSet rs = null;
2983
        String fieldValue = null;
2984
        String docId = null;
2985
        DBConnection conn = null;
2986
        int serialNumber = -1;
2987

    
2988
        // get rid of revision if access number has
2989
        docId = MetaCatUtil.getDocIdFromString(accessionNumber);
2990
        try {
2991
            //check out DBConnection
2992
            conn = DBConnectionPool
2993
                    .getDBConnection("MetaCatServlet.getPublicIdForDoc");
2994
            serialNumber = conn.getCheckOutSerialNumber();
2995
            pstmt = conn.prepareStatement("SELECT " + fieldName
2996
                    + " FROM xml_documents " + "WHERE docid = ? ");
2997

    
2998
            pstmt.setString(1, docId);
2999
            pstmt.execute();
3000
            rs = pstmt.getResultSet();
3001
            boolean hasRow = rs.next();
3002
            int perm = 0;
3003
            if (hasRow) {
3004
                fieldValue = rs.getString(1);
3005
            } else {
3006
                throw new Exception("Could not find document: "
3007
                        + accessionNumber);
3008
            }
3009
        } catch (Exception e) {
3010
            logMetacat.error(
3011
                    "Exception in MetacatServlet.getPublicIdForDoc: "
3012
                            + e.getMessage());
3013
            throw e;
3014
        } finally {
3015
            try {
3016
                rs.close();
3017
                pstmt.close();
3018

    
3019
            } finally {
3020
                DBConnectionPool.returnDBConnection(conn, serialNumber);
3021
            }
3022
        }
3023
        return fieldValue;
3024
    }
3025

    
3026
    /*
3027
     * Get the list of documents from the database and return the list in an
3028
     * Vector of identifiers.
3029
     *
3030
     * @ returns the array of identifiers
3031
     */
3032
    private Vector getDocumentList() throws SQLException
3033
    {
3034
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
3035
        Vector docList = new Vector();
3036
        PreparedStatement pstmt = null;
3037
        ResultSet rs = null;
3038
        DBConnection conn = null;
3039
        int serialNumber = -1;
3040

    
3041
        try {
3042
            //check out DBConnection
3043
            conn = DBConnectionPool
3044
                    .getDBConnection("MetaCatServlet.getDocumentList");
3045
            serialNumber = conn.getCheckOutSerialNumber();
3046
            pstmt = conn.prepareStatement("SELECT docid, rev"
3047
                    + " FROM xml_documents ");
3048
            pstmt.execute();
3049
            rs = pstmt.getResultSet();
3050
            while (rs.next()) {
3051
                String docid = rs.getString(1);
3052
                String rev = rs.getString(2);
3053
                docList.add(docid + "." + rev);
3054
            }
3055
        } catch (SQLException e) {
3056
            logMetacat.error(
3057
                    "Exception in MetacatServlet.getDocumentList: "
3058
                            + e.getMessage());
3059
            throw e;
3060
        } finally {
3061
            try {
3062
                rs.close();
3063
                pstmt.close();
3064

    
3065
            } catch (SQLException se) {
3066
                logMetacat.error(
3067
                    "Exception in MetacatServlet.getDocumentList: "
3068
                            + se.getMessage());
3069
                throw se;
3070
            } finally {
3071
                DBConnectionPool.returnDBConnection(conn, serialNumber);
3072
            }
3073
        }
3074
        return docList;
3075
    }
3076

    
3077
    /*
3078
     * A method to output setAccess action result
3079
     */
3080
    private void outputResponse(Vector successList, Vector errorList,
3081
            PrintWriter out)
3082
    {
3083
        boolean error = false;
3084
        boolean success = false;
3085
        // Output prolog
3086
        out.println(PROLOG);
3087
        // output success message
3088
        if (successList != null) {
3089
            for (int i = 0; i < successList.size(); i++) {
3090
                out.println(SUCCESS);
3091
                out.println((String) successList.elementAt(i));
3092
                out.println(SUCCESSCLOSE);
3093
                success = true;
3094
            }
3095
        }
3096
        // output error message
3097
        if (errorList != null) {
3098
            for (int i = 0; i < errorList.size(); i++) {
3099
                out.println(ERROR);
3100
                out.println((String) errorList.elementAt(i));
3101
                out.println(ERRORCLOSE);
3102
                error = true;
3103
            }
3104
        }
3105

    
3106
        // if no error and no success info, send a error that nothing happened
3107
        if (!error && !success) {
3108
            out.println(ERROR);
3109
            out.println("Nothing happend for setaccess action");
3110
            out.println(ERRORCLOSE);
3111
        }
3112
    }
3113
    
3114
    /**
3115
     * Method to get session table which store the session info
3116
     * @return
3117
     */
3118
    public static Hashtable getSessionHash()
3119
    {
3120
        return sessionHash;
3121
    }
3122
    
3123
    /*
3124
     * If the given docid only have one seperter, we need 
3125
     * append rev for it. The rev come from xml_documents
3126
     */
3127
    private static String appendRev(String docid) throws Exception
3128
    {
3129
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
3130
        String newAccNum = null;
3131
        String separator = MetaCatUtil.getOption("accNumSeparator");
3132
        int firstIndex = docid.indexOf(separator);
3133
        int lastIndex = docid.lastIndexOf(separator);
3134
        if (firstIndex == lastIndex)
3135
        {
3136
            
3137
           //only one seperater
3138
            int rev = DBUtil.getLatestRevisionInDocumentTable(docid);
3139
            if (rev == -1)
3140
            {
3141
                throw new Exception("the requested docid '"
3142
                        + docid+ "' does not exist");
3143
            }
3144
            else
3145
            {
3146
                newAccNum = docid+ separator+ rev;
3147
            }
3148
        }
3149
        else
3150
        {
3151
            // in other suituation we don't change the docid
3152
            newAccNum = docid;
3153
        }
3154
        //logMetacat.debug("The docid will be read is "+newAccNum);
3155
        return newAccNum;
3156
  }
3157
}
(44-44/65)