Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2010 Regents of the University of California and the
4
 *             National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author: jones $'
7
 *     '$Date: 2010-02-03 17:58:12 -0900 (Wed, 03 Feb 2010) $'
8
 * '$Revision: 5211 $'
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program; if not, write to the Free Software
22
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 */
24

    
25
package edu.ucsb.nceas.metacat;
26

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

    
55
import javax.servlet.ServletContext;
56
import javax.servlet.ServletOutputStream;
57
import javax.servlet.http.HttpServletRequest;
58
import javax.servlet.http.HttpServletResponse;
59
import javax.servlet.http.HttpSession;
60
import javax.activation.MimetypesFileTypeMap;
61

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

    
65
import au.com.bytecode.opencsv.CSVWriter;
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.metacat.accesscontrol.AccessControlException;
73
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlForSingleFile;
74
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlInterface;
75
import edu.ucsb.nceas.metacat.cart.CartManager;
76
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
77
import edu.ucsb.nceas.metacat.database.DBConnection;
78
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
79
import edu.ucsb.nceas.metacat.dataquery.DataQuery;
80
import edu.ucsb.nceas.metacat.properties.PropertyService;
81
import edu.ucsb.nceas.metacat.replication.ForceReplicationHandler;
82
import edu.ucsb.nceas.metacat.service.SessionService;
83
import edu.ucsb.nceas.metacat.service.XMLSchemaService;
84
import edu.ucsb.nceas.metacat.shared.MetacatUtilException;
85
import edu.ucsb.nceas.metacat.shared.ServiceException;
86
import edu.ucsb.nceas.metacat.spatial.SpatialHarvester;
87
import edu.ucsb.nceas.metacat.spatial.SpatialQuery;
88
import edu.ucsb.nceas.metacat.util.AuthUtil;
89
import edu.ucsb.nceas.metacat.util.DocumentUtil;
90
import edu.ucsb.nceas.metacat.util.MetacatUtil;
91
import edu.ucsb.nceas.metacat.util.RequestUtil;
92
import edu.ucsb.nceas.metacat.util.SystemUtil;
93
import edu.ucsb.nceas.utilities.FileUtil;
94
import edu.ucsb.nceas.utilities.LSIDUtil;
95
import edu.ucsb.nceas.utilities.ParseLSIDException;
96
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
97

    
98
/**
99
 * General entry point for the Metacat server which is called from various 
100
 * mechanisms such as the standard MetacatServlet class and the various web
101
 * service servlets such as RestServlet class.  All application logic should be
102
 * encapsulated in this class, and the calling classes should only contain
103
 * parameter marshaling and demarshaling code, delegating all else to this
104
 * MetacatHandler instance.
105
 * @author Matthew Jones
106
 */
107
public class MetacatHandler {
108

    
109
    private static boolean _sitemapScheduled = false;
110

    
111
    // Constants -- these should be final in a servlet    
112
    private static final String PROLOG = "<?xml version=\"1.0\"?>";
113
    private static final String SUCCESS = "<success>";
114
    private static final String SUCCESSCLOSE = "</success>";
115
    private static final String ERROR = "<error>";
116
    private static final String ERRORCLOSE = "</error>";
117
    
118
	private Timer timer;
119
	
120
    public MetacatHandler(Timer timer) {
121
    	this.timer = timer;
122
    }
123
    
124
    
125
    protected void handleDataquery(
126
            Hashtable<String, String[]> params,
127
            HttpServletResponse response,
128
            String sessionId) throws PropertyNotFoundException, IOException {
129
        
130
        DataQuery dq = null;
131
        if (sessionId != null) {
132
            dq = new DataQuery(sessionId);
133
        }
134
        else {
135
            dq = new DataQuery();
136
        }
137
        
138
        String dataqueryXML = (params.get("dataquery"))[0];
139

    
140
        ResultSet rs = null;
141
        try {
142
            rs = dq.executeQuery(dataqueryXML);
143
        } catch (Exception e) {
144
            //probably need to do something here
145
            e.printStackTrace();
146
            return;
147
        }
148
        
149
        //process the result set
150
        String qformat = "csv";
151
        String[] temp = params.get("qformat");
152
        if (temp != null && temp.length > 0) {
153
            qformat = temp[0];
154
        }
155
        String fileName = "query-results." + qformat;
156
        
157
        //get the results as csv file
158
        if (qformat != null && qformat.equalsIgnoreCase("csv")) {
159
            response.setContentType("text/csv");
160
            //response.setContentType("application/csv");
161
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
162
            
163
            Writer writer = new OutputStreamWriter(response.getOutputStream());
164
            CSVWriter csv = new CSVWriter(writer, CSVWriter.DEFAULT_SEPARATOR, CSVWriter.NO_QUOTE_CHARACTER);
165
            try {
166
                
167
                csv.writeAll(rs, true);
168
                
169
                csv.flush();
170
                response.flushBuffer();
171
                
172
                rs.close();
173
                
174
            } catch (SQLException e) {
175
                e.printStackTrace();
176
            }
177
            
178
            return;
179
        }
180
        
181
    }
182
    
183
    protected void handleEditCart(
184
            Hashtable<String, String[]> params,
185
            HttpServletResponse response,
186
            String sessionId) throws PropertyNotFoundException, IOException {
187
        
188
        CartManager cm = null;
189
        if (sessionId != null) {
190
            cm = new CartManager(sessionId);
191
        }
192
        else {
193
            cm = new CartManager();
194
        }
195
        
196
        String editOperation = (params.get("operation"))[0];
197
        
198
        String[] docids = params.get("docid");
199
        String[] field = params.get("field");
200
        String[] path = params.get("path");
201
        
202
        Map<String,String> fields = null;
203
        if (field != null && path != null) {
204
            fields = new HashMap<String,String>();
205
            fields.put(field[0], path[0]);
206
        }
207
        
208
        //TODO handle attribute map (metadata fields)
209
        cm.editCart(editOperation, docids, fields);
210
        
211
    }
212
    
213
    // ///////////////////////////// METACAT SPATIAL ///////////////////////////
214
    
215
    /**
216
     * handles all spatial queries -- these queries may include any of the
217
     * queries supported by the WFS / WMS standards
218
     * 
219
     * handleSQuery(out, params, response, username, groupnames, sess_id);
220
     */
221
    protected void handleSpatialQuery(PrintWriter out, Hashtable<String, String[]> params,
222
            HttpServletResponse response,
223
            String username, String[] groupnames,
224
            String sess_id) throws PropertyNotFoundException {
225
        
226
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
227
        
228
        if ( !PropertyService.getProperty("spatial.runSpatialOption").equals("true") ) {
229
            response.setContentType("text/html");
230
            out.println("<html> Metacat Spatial Option is turned off </html>");
231
            out.close();
232
            return ;
233
        }
234
        
235
        /*
236
         * Perform spatial query against spatial cache
237
         */
238
        float _xmax = Float.valueOf( (params.get("xmax"))[0] ).floatValue();
239
        float _ymax = Float.valueOf( (params.get("ymax"))[0] ).floatValue();
240
        float _xmin = Float.valueOf( (params.get("xmin"))[0] ).floatValue();
241
        float _ymin = Float.valueOf( (params.get("ymin"))[0] ).floatValue();
242
        SpatialQuery sq = new SpatialQuery();
243
        Vector<String> docids = sq.filterByBbox( _xmin, _ymin, _xmax, _ymax );
244
        // logMetacat.info(" --- Spatial Query completed. Passing on the SQuery
245
        // handler");
246
        // logMetacat.warn("\n\n ******* after spatial query, we've got " +
247
        // docids.size() + " docids \n\n");
248
        
249
        /*
250
         * Create an array matching docids
251
         */
252
        String [] docidArray = new String[docids.size()];
253
        docids.toArray(docidArray);
254
        
255
        /*
256
         * Create squery string
257
         */
258
        String squery = DocumentIdQuery.createDocidQuery( docidArray );
259
        // logMetacat.info("-----------\n" + squery + "\n------------------");
260
        String[] queryArray = new String[1];
261
        queryArray[0] = squery;
262
        params.put("query", queryArray);
263
        
264
        /*
265
         * Determine qformat
266
         */
267
        String[] qformatArray = new String[1];
268
        try {
269
            String _skin = (params.get("skin"))[0];
270
            qformatArray[0] = _skin;
271
        } catch (java.lang.NullPointerException e) {
272
            // should be "default" but keep this for backwards compatibility
273
            // with knp site
274
            logMetacat.warn("MetaCatServlet.handleSpatialQuery - No SKIN specified for metacat actions=spatial_query... defaulting to 'knp' skin !\n");
275
            qformatArray[0] = "knp";
276
        }
277
        params.put("qformat", qformatArray);
278
        
279
        // change the action
280
        String[] actionArray = new String[1];
281
        actionArray[0] = "squery";
282
        params.put("action", actionArray);
283
        
284
        /*
285
         * Pass the docids to the DBQuery contructor
286
         */
287
        // This is a hack to get the empty result set to show...
288
        // Otherwise dbquery sees no docidOverrides and does a full % percent
289
        // query
290
        if (docids.size() == 0)
291
            docids.add("");
292
        
293
        DBQuery queryobj = new DBQuery(docids);
294
        queryobj.findDocuments(response, out, params, username, groupnames, sess_id);
295
        
296
    }
297
    
298
    // LOGIN & LOGOUT SECTION
299
    /**
300
     * Handle the login request. Create a new session object. Do user
301
     * authentication through the session.
302
     */
303
    public void handleLoginAction(PrintWriter out, Hashtable<String, String[]> params,
304
            HttpServletRequest request, HttpServletResponse response) {
305
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
306
        AuthSession sess = null;
307
        
308
        if(params.get("username") == null){
309
            response.setContentType("text/xml");
310
            out.println("<?xml version=\"1.0\"?>");
311
            out.println("<error>");
312
            out.println("Username not specified");
313
            out.println("</error>");
314
            return;
315
        }
316
        
317
        // }
318
        
319
        if(params.get("password") == null){
320
            response.setContentType("text/xml");
321
            out.println("<?xml version=\"1.0\"?>");
322
            out.println("<error>");
323
            out.println("Password not specified");
324
            out.println("</error>");
325
            return;
326
        }
327
        
328
        String un = (params.get("username"))[0];
329
        logMetacat.info("MetaCatServlet.handleLoginAction - user " + un + " is trying to login");
330
        String pw = (params.get("password"))[0];
331
        
332
        String qformat = "xml";
333
        if (params.get("qformat") != null) {
334
            qformat = (params.get("qformat"))[0];
335
        }
336
        
337
        try {
338
            sess = new AuthSession();
339
        } catch (Exception e) {
340
            String errorMsg = "MetacatServlet.handleLoginAction - Problem in MetacatServlet.handleLoginAction() authenicating session: "
341
                + e.getMessage();
342
            logMetacat.error(errorMsg);
343
            out.println(errorMsg);
344
            e.printStackTrace(System.out);
345
            return;
346
        }
347
        boolean isValid = sess.authenticate(request, un, pw);
348
        
349
        //if it is authernticate is true, store the session
350
        if (isValid) {
351
            HttpSession session = sess.getSessions();
352
            String id = session.getId();
353
            
354
            logMetacat.debug("MetaCatServlet.handleLoginAction - Store session id " + id
355
                    + " which has username" + session.getAttribute("username")
356
                    + " into hash in login method");
357
            try {
358
                SessionService.registerSession(id, 
359
                        (String) session.getAttribute("username"), 
360
                        (String[]) session.getAttribute("groupnames"), 
361
                        (String) session.getAttribute("password"), 
362
                        (String) session.getAttribute("name"));
363
            } catch (ServiceException se) {
364
                String errorMsg = "MetacatServlet.handleLoginAction - service problem registering session: "
365
                        + se.getMessage();
366
                logMetacat.error("MetaCatServlet.handleLoginAction - " + errorMsg);
367
                out.println(errorMsg);
368
                se.printStackTrace(System.out);
369
                return;
370
            }           
371
        }
372
                
373
        // format and transform the output
374
        if (qformat.equals("xml")) {
375
            response.setContentType("text/xml");
376
            out.println(sess.getMessage());
377
        } else {
378
            try {
379
                DBTransform trans = new DBTransform();
380
                response.setContentType("text/html");
381
                trans.transformXMLDocument(sess.getMessage(),
382
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
383
                        out, null, null);
384
            } catch (Exception e) {               
385
                logMetacat.error("MetaCatServlet.handleLoginAction - General error"
386
                        + e.getMessage());
387
                e.printStackTrace(System.out);
388
            }
389
        }
390
    }
391
    
392
    /**
393
     * Handle the logout request. Close the connection.
394
     */
395
    public void handleLogoutAction(PrintWriter out, Hashtable<String, String[]> params,
396
            HttpServletRequest request, HttpServletResponse response) {
397
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
398
        String qformat = "xml";
399
        if(params.get("qformat") != null){
400
            qformat = params.get("qformat")[0];
401
        }
402
        
403
        // close the connection
404
        HttpSession sess = request.getSession(false);
405
        logMetacat.info("MetaCatServlet.handleLogoutAction - After get session in logout request");
406
        if (sess != null) {
407
            logMetacat.info("MetaCatServlet.handleLogoutAction - The session id " + sess.getId()
408
            + " will be invalidate in logout action");
409
            logMetacat.info("MetaCatServlet.handleLogoutAction - The session contains user "
410
                    + sess.getAttribute("username")
411
                    + " will be invalidate in logout action");
412
            sess.invalidate();
413
            SessionService.unRegisterSession(sess.getId());
414
        }
415
        
416
        // produce output
417
        StringBuffer output = new StringBuffer();
418
        output.append("<?xml version=\"1.0\"?>");
419
        output.append("<logout>");
420
        output.append("User logged out");
421
        output.append("</logout>");
422
        
423
        //format and transform the output
424
        if (qformat.equals("xml")) {
425
            response.setContentType("text/xml");
426
            out.println(output.toString());
427
        } else {
428
            try {
429
                DBTransform trans = new DBTransform();
430
                response.setContentType("text/html");
431
                trans.transformXMLDocument(output.toString(),
432
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
433
                        out, null, null);
434
            } catch (Exception e) {
435
                logMetacat.error(
436
                        "MetaCatServlet.handleLogoutAction - General error: "
437
                        + e.getMessage());
438
                e.printStackTrace(System.out);
439
            }
440
        }
441
    }
442
    
443
    // END OF LOGIN & LOGOUT SECTION
444
    
445
    // SQUERY & QUERY SECTION
446
    /**
447
     * Retreive the squery xml, execute it and display it
448
     *
449
     * @param out the output stream to the client
450
     * @param params the Hashtable of parameters that should be included in the
451
     *            squery.
452
     * @param response the response object linked to the client
453
     * @param conn the database connection
454
     */
455
    protected void handleSQuery(PrintWriter out, Hashtable<String, String[]> params,
456
            HttpServletResponse response, String user, String[] groups,
457
            String sessionid) throws PropertyNotFoundException {
458
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
459
        long squeryWarnLimit = Long.parseLong(PropertyService.getProperty("database.squeryTimeWarnLimit"));
460
        
461
        long startTime = System.currentTimeMillis();
462
        DBQuery queryobj = new DBQuery();
463
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
464
        long outPutTime = System.currentTimeMillis();
465
        long runTime = outPutTime - startTime;
466

    
467
        if (runTime > squeryWarnLimit) {
468
            logMetacat.warn("MetaCatServlet.handleSQuery - Long running squery.  Total time: " + runTime + 
469
                    " ms, squery: " + ((String[])params.get("query"))[0]);
470
        }
471
        logMetacat.debug("MetaCatServlet.handleSQuery - squery: " + ((String[])params.get("query"))[0] + 
472
                " ran in " + runTime + " ms");
473
    }
474
    
475
    /**
476
     * Create the xml query, execute it and display the results.
477
     *
478
     * @param out the output stream to the client
479
     * @param params the Hashtable of parameters that should be included in the
480
     *            squery.
481
     * @param response the response object linked to the client
482
     */
483
    protected void handleQuery(PrintWriter out, Hashtable<String, String[]> params,
484
            HttpServletResponse response, String user, String[] groups,
485
            String sessionid) throws PropertyNotFoundException {
486
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
487
        long queryWarnLimit = Long.parseLong(PropertyService.getProperty("database.queryTimeWarnLimit"));
488
        
489
        //create the query and run it
490
        String xmlquery = DBQuery.createSQuery(params);
491
        String[] queryArray = new String[1];
492
        queryArray[0] = xmlquery;
493
        params.put("query", queryArray);
494
        long startTime = System.currentTimeMillis();
495
        DBQuery queryobj = new DBQuery();
496
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
497
        long outPutTime = System.currentTimeMillis();
498
        long runTime = outPutTime -startTime;
499

    
500
        if (runTime > queryWarnLimit) {
501
            logMetacat.warn("MetaCatServlet.handleQuery - Long running squery.  Total time: " + runTime + 
502
                    " ms, squery: " + ((String[])params.get("query"))[0]);
503
        }
504
        logMetacat.debug("MetaCatServlet.handleQuery - query: " + ((String[])params.get("query"))[0] + 
505
                " ran in " + runTime + " ms");
506
    }
507
    
508
    // END OF SQUERY & QUERY SECTION
509
    
510
    //Export section
511
    /**
512
     * Handle the "export" request of data package from Metacat in zip format
513
     *
514
     * @param params the Hashtable of HTTP request parameters
515
     * @param response the HTTP response object linked to the client
516
     * @param user the username sent the request
517
     * @param groups the user's groupnames
518
     */
519
    protected void handleExportAction(Hashtable<String, String[]> params,
520
            HttpServletResponse response,
521
            String user, String[] groups, String passWord) {
522
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
523
        // Output stream
524
        ServletOutputStream out = null;
525
        // Zip output stream
526
        ZipOutputStream zOut = null;
527
        DBQuery queryObj = null;
528
        
529
        String[] docs = new String[10];
530
        String docId = "";
531
        
532
        try {
533
            // read the params
534
            if (params.containsKey("docid")) {
535
                docs = params.get("docid");
536
            }
537
            // Create a DBuery to handle export
538
            queryObj = new DBQuery();
539
            // Get the docid
540
            docId = docs[0];
541
            // Make sure the client specify docid
542
            if (docId == null || docId.equals("")) {
543
                response.setContentType("text/xml"); //MIME type
544
                // Get a printwriter
545
                PrintWriter pw = response.getWriter();
546
                // Send back message
547
                pw.println("<?xml version=\"1.0\"?>");
548
                pw.println("<error>");
549
                pw.println("You didn't specify requested docid");
550
                pw.println("</error>");
551
                // Close printwriter
552
                pw.close();
553
                return;
554
            }
555
            // Get output stream
556
            out = response.getOutputStream();
557
            response.setContentType("application/zip"); //MIME type
558
            response.setHeader("Content-Disposition",
559
                    "attachment; filename="
560
                    + docId + ".zip"); // Set the name of the zip file
561
            
562
            zOut = new ZipOutputStream(out);
563
            zOut = queryObj
564
                    .getZippedPackage(docId, out, user, groups, passWord);
565
            zOut.finish(); //terminate the zip file
566
            zOut.close(); //close the zip stream
567
            
568
        } catch (Exception e) {
569
            try {
570
                response.setContentType("text/xml"); //MIME type
571
                // Send error message back
572
                if (out != null) {
573
                    PrintWriter pw = new PrintWriter(out);
574
                    pw.println("<?xml version=\"1.0\"?>");
575
                    pw.println("<error>");
576
                    pw.println(e.getMessage());
577
                    pw.println("</error>");
578
                    // Close printwriter
579
                    pw.close();
580
                    // Close output stream
581
                    out.close();
582
                }
583
                // Close zip output stream
584
                if (zOut != null) {
585
                    zOut.close();
586
                }
587
            } catch (IOException ioe) {
588
                logMetacat.error("MetaCatServlet.handleExportAction - Problem with the servlet output: "
589
                        + ioe.getMessage());
590
                e.printStackTrace(System.out);
591
            }
592
            
593
            logMetacat.error("MetaCatServlet.handleExportAction - General error: "
594
                    + e.getMessage());
595
            e.printStackTrace(System.out);
596
            
597
        }
598
        
599
    }
600
    
601
    /**
602
     * In eml2 document, the xml can have inline data and data was stripped off
603
     * and store in file system. This action can be used to read inline data
604
     * only
605
     *
606
     * @param params the Hashtable of HTTP request parameters
607
     * @param response the HTTP response object linked to the client
608
     * @param user the username sent the request
609
     * @param groups the user's groupnames
610
     */
611
    protected void handleReadInlineDataAction(Hashtable<String, String[]> params,
612
            HttpServletRequest request, HttpServletResponse response,
613
            String user, String passWord, String[] groups) {
614
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
615
        String[] docs = new String[10];
616
        String inlineDataId = null;
617
        String docId = "";
618
        ServletOutputStream out = null;
619
        
620
        try {
621
            // read the params
622
            if (params.containsKey("inlinedataid")) {
623
                docs = params.get("inlinedataid");
624
            }
625
            // Get the docid
626
            inlineDataId = docs[0];
627
            // Make sure the client specify docid
628
            if (inlineDataId == null || inlineDataId.equals("")) {
629
                throw new Exception("You didn't specify requested inlinedataid"); }
630
            
631
            // check for permission
632
            docId = 
633
                DocumentUtil.getDocIdWithoutRevFromInlineDataID(inlineDataId);
634
            PermissionController controller = new PermissionController(docId);
635
            // check top level read permission
636
            if (!controller.hasPermission(user, groups,
637
                    AccessControlInterface.READSTRING)) {
638
                throw new Exception("User " + user
639
                        + " doesn't have permission " + " to read document "
640
                        + docId);
641
            } else {
642
                //check data access level
643
                try {
644
                    Hashtable<String,String> unReadableInlineDataList =
645
                            PermissionController.getUnReadableInlineDataIdList(docId,
646
                            user, groups, false);
647
                    String inlineDataIdWithoutRev = DocumentUtil.getInlineDataIdWithoutRev(inlineDataId);
648
                    if (unReadableInlineDataList.containsValue(inlineDataIdWithoutRev)) {
649
                        throw new Exception("User " + user
650
                                + " doesn't have permission " + " to read inlinedata "
651
                                + inlineDataId);
652
                        
653
                    }//if
654
                }//try
655
                catch (Exception e) {
656
                    throw e;
657
                }//catch
658
            }//else
659
            
660
            // Get output stream
661
            out = response.getOutputStream();
662
            // read the inline data from the file
663
            String inlinePath = PropertyService.getProperty("application.inlinedatafilepath");
664
            File lineData = new File(inlinePath, inlineDataId);
665
            FileInputStream input = new FileInputStream(lineData);
666
            byte[] buffer = new byte[4 * 1024];
667
            int bytes = input.read(buffer);
668
            while (bytes != -1) {
669
                out.write(buffer, 0, bytes);
670
                bytes = input.read(buffer);
671
            }
672
            out.close();
673
            
674
            EventLog.getInstance().log(request.getRemoteAddr(), user,
675
                    inlineDataId, "readinlinedata");
676
        } catch (Exception e) {
677
            try {
678
                PrintWriter pw = null;
679
                // Send error message back
680
                if (out != null) {
681
                    pw = new PrintWriter(out);
682
                } else {
683
                    pw = response.getWriter();
684
                }
685
                pw.println("<?xml version=\"1.0\"?>");
686
                pw.println("<error>");
687
                pw.println(e.getMessage());
688
                pw.println("</error>");
689
                // Close printwriter
690
                pw.close();
691
                // Close output stream if out is not null
692
                if (out != null) {
693
                    out.close();
694
                }
695
            } catch (IOException ioe) {
696
                logMetacat.error("MetaCatServlet.handleReadInlineDataAction - Problem with the servlet output: "
697
                        + ioe.getMessage());
698
                e.printStackTrace(System.out);
699
            }
700
            logMetacat.error("MetaCatServlet.handleReadInlineDataAction - General error: "
701
                    + e.getMessage());
702
            e.printStackTrace(System.out);
703
        }
704
    }
705
    
706
    /**
707
     * Handle the "read" request of metadata/data files from Metacat or any
708
     * files from Internet; transformed metadata XML document into HTML
709
     * presentation if requested; zip files when more than one were requested.
710
     *
711
     * @param params the Hashtable of HTTP request parameters
712
     * @param request the HTTP request object linked to the client
713
     * @param response the HTTP response object linked to the client
714
     * @param user the username sent the request
715
     * @param groups the user's groupnames
716
     */
717
    public void handleReadAction(Hashtable<String, String[]> params, HttpServletRequest request,
718
            HttpServletResponse response, String user, String passWord,
719
            String[] groups) {
720
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
721
        ServletOutputStream out = null;
722
        ZipOutputStream zout = null;
723
        PrintWriter pw = null;
724
        boolean zip = false;
725
        boolean withInlineData = true;
726
        
727
        try {
728
            String[] docs = new String[0];
729
            String docid = "";
730
            String qformat = "";
731
            
732
            // read the params
733
            if (params.containsKey("docid")) {
734
                docs = params.get("docid");
735
            }
736
            if (params.containsKey("qformat")) {
737
                qformat = params.get("qformat")[0];
738
            }
739
            // the param for only metadata (eml)
740
            // we don't support read a eml document without inline data now.
741
            /*if (params.containsKey("inlinedata")) {
742
             
743
                String inlineData = ((String[]) params.get("inlinedata"))[0];
744
                if (inlineData.equalsIgnoreCase("false")) {
745
                    withInlineData = false;
746
                }
747
            }*/
748
            if ((docs.length > 1) || qformat.equals("zip")) {
749
                zip = true;
750
                out = response.getOutputStream();
751
                response.setContentType("application/zip"); //MIME type
752
                zout = new ZipOutputStream(out);
753
            }
754
            // go through the list of docs to read
755
            for (int i = 0; i < docs.length; i++) {
756
                String providedFileName = null;
757
                if (params.containsKey(docs[i])) {
758
                    providedFileName = params.get(docs[i])[0];
759
                }
760
                try {
761
                    
762
                    URL murl = new URL(docs[i]);
763
                    Hashtable<String,String> murlQueryStr = MetacatUtil.parseQuery(
764
                            murl.getQuery());
765
                    // case docid="http://.../?docid=aaa"
766
                    // or docid="metacat://.../?docid=bbb"
767
                    if (murlQueryStr.containsKey("docid")) {
768
                        // get only docid, eliminate the rest
769
                        docid = murlQueryStr.get("docid");
770
                        if (zip) {
771
                            addDocToZip(request, docid, providedFileName, zout, user, groups);
772
                        } else {
773
                            readFromMetacat(request.getRemoteAddr(), response, response.getOutputStream(), docid, qformat,
774
                                    user, groups, withInlineData, params);
775
                        }
776
                        
777
                        // case docid="http://.../filename"
778
                    } else {
779
                        docid = docs[i];
780
                        if (zip) {
781
                            addDocToZip(request, docid, providedFileName, zout, user, groups);
782
                        } else {
783
                            readFromURLConnection(response, docid);
784
                        }
785
                    }
786
                    
787
                } catch (MalformedURLException mue) {
788
                    docid = docs[i];
789
                    if (zip) {
790
                        addDocToZip(request, docid, providedFileName, zout, user, groups);
791
                    } else {
792
                    	if (out == null) {
793
                    		out = response.getOutputStream();
794
                    	}
795
                        readFromMetacat(request.getRemoteAddr(), response, out, docid, qformat,
796
                                user, groups, withInlineData, params);
797
                    }
798
                }
799
            }
800
            
801
            if (zip) {
802
                zout.finish(); //terminate the zip file
803
                zout.close(); //close the zip stream
804
            }
805
            
806
        } catch (McdbDocNotFoundException notFoundE) {
807
            // To handle doc not found exception
808
            // the docid which didn't be found
809
            String notFoundDocId = notFoundE.getUnfoundDocId();
810
            String notFoundRevision = notFoundE.getUnfoundRevision();
811
            logMetacat.warn("MetaCatServlet.handleReadAction - Missed id: " + notFoundDocId);
812
            logMetacat.warn("MetaCatServlet.handleReadAction - Missed rev: " + notFoundRevision);
813
            try {
814
                // read docid from remote server
815
                readFromRemoteMetaCat(response, notFoundDocId,
816
                        notFoundRevision, user, passWord, out, zip, zout);
817
                // Close zout outputstream
818
                if (zout != null) {
819
                    zout.close();
820
                }
821
                // close output stream
822
                if (out != null) {
823
                    out.close();
824
                }
825
                
826
            } catch (Exception exc) {
827
                logMetacat.error("MetaCatServlet.handleReadAction - General error: "
828
                        + exc.getMessage());
829
                exc.printStackTrace(System.out);
830
                try {
831
                    if (out != null) {
832
                        response.setContentType("text/xml");
833
                        // Send back error message by printWriter
834
                        pw = new PrintWriter(out);
835
                        pw.println("<?xml version=\"1.0\"?>");
836
                        pw.println("<error>");
837
                        pw.println(notFoundE.getMessage());
838
                        pw.println("</error>");
839
                        pw.close();
840
                        out.close();
841
                        
842
                    } else {
843
                        response.setContentType("text/xml"); //MIME type
844
                        // Send back error message if out = null
845
                        if (pw == null) {
846
                            // If pw is null, open the respnose
847
                            pw = response.getWriter();
848
                        }
849
                        pw.println("<?xml version=\"1.0\"?>");
850
                        pw.println("<error>");
851
                        pw.println(notFoundE.getMessage());
852
                        pw.println("</error>");
853
                        pw.close();
854
                    }
855
                    // close zout
856
                    if (zout != null) {
857
                        zout.close();
858
                    }
859
                } catch (IOException ie) {
860
                    logMetacat.error("MetaCatServlet.handleReadAction - Problem with the servlet output: "
861
                            + ie.getMessage());
862
                    ie.printStackTrace(System.out);
863
                }
864
            }
865
        } catch (Exception e) {
866
            try {
867
                
868
                if (out != null) {
869
                    response.setContentType("text/xml"); //MIME type
870
                    pw = new PrintWriter(out);
871
                    pw.println("<?xml version=\"1.0\"?>");
872
                    pw.println("<error>");
873
                    pw.println(e.getMessage());
874
                    pw.println("</error>");
875
                    pw.close();
876
                    out.close();
877
                } else {
878
                    response.setContentType("text/xml"); //MIME type
879
                    // Send back error message if out = null
880
                    if (pw == null) {
881
                        pw = response.getWriter();
882
                    }
883
                    pw.println("<?xml version=\"1.0\"?>");
884
                    pw.println("<error>");
885
                    pw.println(e.getMessage());
886
                    pw.println("</error>");
887
                    pw.close();
888
                    
889
                }
890
                // Close zip output stream
891
                if (zout != null) {
892
                    zout.close();
893
                }
894
                
895
            } catch (Exception e2) {
896
                logMetacat.error("MetaCatServlet.handleReadAction - Problem with the servlet output: "
897
                        + e2.getMessage());
898
                e2.printStackTrace(System.out);
899
                
900
            }
901
            
902
            logMetacat.error("MetaCatServlet.handleReadAction - General error: "
903
                    + e.getMessage());
904
            e.printStackTrace(System.out);
905
        }
906
    }
907
    
908
    /** read metadata or data from Metacat
909
     * @throws PropertyNotFoundException 
910
     * @throws ParseLSIDException 
911
     * @throws InsufficientKarmaException 
912
     */
913
    public void readFromMetacat(String ipAddress,
914
            HttpServletResponse response, OutputStream out, String docid, String qformat,
915
            String user, String[] groups, boolean withInlineData, 
916
            Hashtable<String, String[]> params) throws ClassNotFoundException, 
917
            IOException, SQLException, McdbException, PropertyNotFoundException, 
918
            ParseLSIDException, InsufficientKarmaException {
919
        
920
        Logger logMetacat = Logger.getLogger(MetacatHandler.class);
921
        try {
922
            
923
            if (docid.startsWith("urn:")) {
924
                docid = LSIDUtil.getDocId(docid, true);                 
925
            }
926
            
927
            // here is hack for handle docid=john.10(in order to tell mike.jim.10.1
928
            // mike.jim.10, we require to provide entire docid with rev). But
929
            // some old client they only provide docid without rev, so we need
930
            // to handle this suituation. First we will check how many
931
            // seperator here, if only one, we will append the rev in xml_documents
932
            // to the id.
933
            docid = appendRev(docid);
934
            
935
            DocumentImpl doc = new DocumentImpl(docid);
936
            
937
            //check the permission for read
938
            if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
939
                InsufficientKarmaException e = new InsufficientKarmaException("User " + user
940
                        + " does not have permission"
941
                        + " to read the document with the docid " + docid);
942
                throw e;
943
            }
944
            
945
            if (doc.getRootNodeID() == 0) {
946
                // this is data file, so find the path on disk for the file
947
                String filepath = PropertyService.getProperty("application.datafilepath");
948
                if (!filepath.endsWith("/")) {
949
                    filepath += "/";
950
                }
951
                String filename = filepath + docid;
952
                FileInputStream fin = null;
953
                fin = new FileInputStream(filename);
954
                
955
                if (response != null) {
956
                    // MIME type
957
                    //String contentType = servletContext.getMimeType(filename);
958
                    String contentType = (new MimetypesFileTypeMap()).getContentType(filename);
959
                    if (contentType == null) {
960
                        ContentTypeProvider provider = new ContentTypeProvider(
961
                                docid);
962
                        contentType = provider.getContentType();
963
                        logMetacat.info("MetaCatServlet.readFromMetacat - Final contenttype is: "
964
                                + contentType);
965
                    }
966
                    response.setContentType(contentType);
967

    
968
                    // Set the output filename on the response
969
                    String outputname = generateOutputName(docid, params, doc);                    
970
                    response.setHeader("Content-Disposition",
971
                            "attachment; filename=\"" + outputname + "\"");
972
                }
973
                
974
                // Write the data to the output stream
975
                try {
976
                    byte[] buf = new byte[4 * 1024]; // 4K buffer
977
                    int b = fin.read(buf);
978
                    while (b != -1) {
979
                        out.write(buf, 0, b);
980
                        b = fin.read(buf);
981
                    }
982
                } finally {
983
                    if (fin != null) fin.close();
984
                }
985
                
986
            } else {
987
                // this is metadata doc
988
                if (qformat.equals("xml") || qformat.equals("")) {
989
                    // if equals "", that means no qformat is specified. hence
990
                    // by default the document should be returned in xml format
991
                    // set content type first
992
                    
993
                    if (response != null) {
994
                        response.setContentType("text/xml"); //MIME type
995
                        response.setHeader("Content-Disposition",
996
                                "attachment; filename=" + docid + ".xml");
997
                    }
998
                    
999
                    // Try to get the metadata file from disk. If it isn't
1000
                    // found, create it from the db and write it to disk then.
1001
                    try {
1002
                        PrintWriter pw = new PrintWriter(out);
1003
                        doc.toXml(pw, user, groups, withInlineData);               
1004
                    } catch (McdbException e) {
1005
                        // any exceptions in reading the xml from disc, and we go back to the
1006
                        // old way of creating the xml directly.
1007
                        logMetacat.error("MetaCatServlet.readFromMetacat - could not read from document file " + docid 
1008
                                + ": " + e.getMessage());
1009
                        e.printStackTrace(System.out);
1010
                        PrintWriter pw = new PrintWriter(out);
1011
                        doc.toXmlFromDb(pw, user, groups, withInlineData);
1012
                    }
1013
                } else {
1014
                    // TODO MCD, this should read from disk as well?
1015
                    //*** This is a metadata doc, to be returned in a skin/custom format.
1016
                    //*** Add param to indicate if public has read access or not.
1017
                    logMetacat.debug("User: \n" + user);
1018
                    if (!user.equals("public")) {
1019
                        if (DocumentImpl.hasReadPermission("public", null, docid))
1020
                            params.put("publicRead", new String[] {"true"});
1021
                        else
1022
                            params.put("publicRead", new String[] {"false"});
1023
                    }
1024
                    
1025
                    if (response != null) {
1026
                        response.setContentType("text/html"); //MIME type
1027
                    }
1028
                    
1029
                    PrintWriter pw = new PrintWriter(out);
1030
                    
1031
                    // Look up the document type
1032
                    String doctype = doc.getDoctype();
1033
                    // Transform the document to the new doctype
1034
                    DBTransform dbt = new DBTransform();
1035
                    dbt.transformXMLDocument(doc.toString(user, groups,
1036
                            withInlineData), doctype, "-//W3C//HTML//EN",
1037
                            qformat, pw, params, null);
1038
                }
1039
                
1040
            }
1041
            EventLog.getInstance().log(ipAddress, user, docid, "read");
1042
        } catch (PropertyNotFoundException except) {
1043
            throw except;
1044
        }
1045
    }
1046

    
1047
    /**
1048
     * Create a filename to be used for naming a downloaded document
1049
     * @param docid the identifier of the document to be named
1050
     * @param params the parameters of the request
1051
     * @param doc the DocumentImpl of the document to be named
1052
     * @return String containing a name for the download
1053
     */
1054
    private String generateOutputName(String docid,
1055
            Hashtable<String, String[]> params, DocumentImpl doc) {
1056
        String outputname = null;
1057
        // check for the existence of a metadatadocid parameter,
1058
        // if this is sent, then send a filename which contains both
1059
        // the metadata docid and the data docid, so the link with
1060
        // metadata is explicitly encoded in the filename.
1061
        String metadatadocid = null;
1062
        Vector<String> nameparts = new Vector<String>();
1063

    
1064
        if(params.containsKey("metadatadocid")) {
1065
            metadatadocid = params.get("metadatadocid")[0];
1066
        }
1067
        if (metadatadocid != null && !metadatadocid.equals("")) {
1068
            nameparts.add(metadatadocid);
1069
        }
1070
        // we'll always have the docid, include it in the name
1071
        String doctype = doc.getDoctype();
1072
        // TODO: fix this to lookup the associated FGDC metadata document,
1073
        // and grab the doctype tag for it.  These should be set to something 
1074
        // consistent, not 'metadata' as it stands...
1075
        //if (!doctype.equals("metadata")) {
1076
        //    nameparts.add(docid);
1077
        //} 
1078
        nameparts.add(docid);
1079
        // Set the name of the data file to the entity name plus docid,
1080
        // or if that is unavailable, use the docid alone
1081
        String docname = doc.getDocname();
1082
        if (docname != null && !docname.equals("")) {
1083
            nameparts.add(docname); 
1084
        }
1085
        // combine the name elements with a dash, using a 'join' equivalent
1086
        String delimiter = "-";
1087
        Iterator<String> iter = nameparts.iterator();
1088
        StringBuffer buffer = new StringBuffer(iter.next());
1089
        while (iter.hasNext()) buffer.append(delimiter).append(iter.next());
1090
        outputname = buffer.toString();
1091
        return outputname;
1092
    }
1093
    
1094
    /**
1095
     * read data from URLConnection
1096
     */
1097
    private void readFromURLConnection(HttpServletResponse response,
1098
            String docid) throws IOException, MalformedURLException {
1099
        ServletOutputStream out = response.getOutputStream();
1100
        //String contentType = servletContext.getMimeType(docid); //MIME type
1101
        String contentType = (new MimetypesFileTypeMap()).getContentType(docid);
1102
        if (contentType == null) {
1103
            if (docid.endsWith(".xml")) {
1104
                contentType = "text/xml";
1105
            } else if (docid.endsWith(".css")) {
1106
                contentType = "text/css";
1107
            } else if (docid.endsWith(".dtd")) {
1108
                contentType = "text/plain";
1109
            } else if (docid.endsWith(".xsd")) {
1110
                contentType = "text/xml";
1111
            } else if (docid.endsWith("/")) {
1112
                contentType = "text/html";
1113
            } else {
1114
                File f = new File(docid);
1115
                if (f.isDirectory()) {
1116
                    contentType = "text/html";
1117
                } else {
1118
                    contentType = "application/octet-stream";
1119
                }
1120
            }
1121
        }
1122
        response.setContentType(contentType);
1123
        // if we decide to use "application/octet-stream" for all data returns
1124
        // response.setContentType("application/octet-stream");
1125
        
1126
        // this is http url
1127
        URL url = new URL(docid);
1128
        BufferedInputStream bis = null;
1129
        try {
1130
            bis = new BufferedInputStream(url.openStream());
1131
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1132
            int b = bis.read(buf);
1133
            while (b != -1) {
1134
                out.write(buf, 0, b);
1135
                b = bis.read(buf);
1136
            }
1137
        } finally {
1138
            if (bis != null) bis.close();
1139
        }
1140
        
1141
    }
1142
    
1143
    /**
1144
     * read file/doc and write to ZipOutputStream
1145
     *
1146
     * @param docid
1147
     * @param zout
1148
     * @param user
1149
     * @param groups
1150
     * @throws ClassNotFoundException
1151
     * @throws IOException
1152
     * @throws SQLException
1153
     * @throws McdbException
1154
     * @throws Exception
1155
     */
1156
    private void addDocToZip(HttpServletRequest request, String docid, String providedFileName,
1157
            ZipOutputStream zout, String user, String[] groups) throws
1158
            ClassNotFoundException, IOException, SQLException, McdbException,
1159
            Exception {
1160
        byte[] bytestring = null;
1161
        ZipEntry zentry = null;
1162
        
1163
        try {
1164
            URL url = new URL(docid);
1165
            
1166
            // this http url; read from URLConnection; add to zip
1167
            //use provided file name if we have one
1168
            if (providedFileName != null && providedFileName.length() > 1) {
1169
                zentry = new ZipEntry(providedFileName);
1170
            }
1171
            else {
1172
                zentry = new ZipEntry(docid);
1173
            }
1174
            zout.putNextEntry(zentry);
1175
            BufferedInputStream bis = null;
1176
            try {
1177
                bis = new BufferedInputStream(url.openStream());
1178
                byte[] buf = new byte[4 * 1024]; // 4K buffer
1179
                int b = bis.read(buf);
1180
                while (b != -1) {
1181
                    zout.write(buf, 0, b);
1182
                    b = bis.read(buf);
1183
                }
1184
            } finally {
1185
                if (bis != null) bis.close();
1186
            }
1187
            zout.closeEntry();
1188
            
1189
        } catch (MalformedURLException mue) {
1190
            
1191
            // this is metacat doc (data file or metadata doc)
1192
            try {
1193
                DocumentImpl doc = new DocumentImpl(docid);
1194
                
1195
                //check the permission for read
1196
                if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1197
                    Exception e = new Exception("User " + user
1198
                            + " does not have "
1199
                            + "permission to read the document with the docid "
1200
                            + docid);
1201
                    throw e;
1202
                }
1203
                
1204
                if (doc.getRootNodeID() == 0) {
1205
                    // this is data file; add file to zip
1206
                    String filepath = PropertyService.getProperty("application.datafilepath");
1207
                    if (!filepath.endsWith("/")) {
1208
                        filepath += "/";
1209
                    }
1210
                    String filename = filepath + docid;
1211
                    FileInputStream fin = null;
1212
                    fin = new FileInputStream(filename);
1213
                    try {
1214
                        //use provided file name if we have one
1215
                        if (providedFileName != null && providedFileName.length() > 1) {
1216
                            zentry = new ZipEntry(providedFileName);
1217
                        }
1218
                        else {
1219
                            zentry = new ZipEntry(docid);
1220
                        }
1221
                        zout.putNextEntry(zentry);
1222
                        byte[] buf = new byte[4 * 1024]; // 4K buffer
1223
                        int b = fin.read(buf);
1224
                        while (b != -1) {
1225
                            zout.write(buf, 0, b);
1226
                            b = fin.read(buf);
1227
                        }
1228
                    } finally {
1229
                        if (fin != null) fin.close();
1230
                    }
1231
                    zout.closeEntry();
1232
                    
1233
                } else {
1234
                    // this is metadata doc; add doc to zip
1235
                    bytestring = doc.toString().getBytes();
1236
                    //use provided file name if given
1237
                    if (providedFileName != null && providedFileName.length() > 1) {
1238
                        zentry = new ZipEntry(providedFileName);
1239
                    }
1240
                    else {
1241
                        zentry = new ZipEntry(docid + ".xml");
1242
                    }
1243
                    zentry.setSize(bytestring.length);
1244
                    zout.putNextEntry(zentry);
1245
                    zout.write(bytestring, 0, bytestring.length);
1246
                    zout.closeEntry();
1247
                }
1248
                EventLog.getInstance().log(request.getRemoteAddr(), user,
1249
                        docid, "read");
1250
            } catch (Exception except) {
1251
                throw except;
1252
            }
1253
        }
1254
    }
1255
    
1256
    /**
1257
     * If metacat couldn't find a data file or document locally, it will read
1258
     * this docid from its home server. This is for the replication feature
1259
     */
1260
    private void readFromRemoteMetaCat(HttpServletResponse response,
1261
            String docid, String rev, String user, String password,
1262
            ServletOutputStream out, boolean zip, ZipOutputStream zout)
1263
            throws Exception {
1264
        // Create a object of RemoteDocument, "" is for zipEntryPath
1265
        RemoteDocument remoteDoc = new RemoteDocument(docid, rev, user,
1266
                password, "");
1267
        String docType = remoteDoc.getDocType();
1268
        // Only read data file
1269
        if (docType.equals("BIN")) {
1270
            // If it is zip format
1271
            if (zip) {
1272
                remoteDoc.readDocumentFromRemoteServerByZip(zout);
1273
            } else {
1274
                if (out == null) {
1275
                    out = response.getOutputStream();
1276
                }
1277
                response.setContentType("application/octet-stream");
1278
                remoteDoc.readDocumentFromRemoteServer(out);
1279
            }
1280
        } else {
1281
            throw new Exception("Docid: " + docid + "." + rev
1282
                    + " couldn't find");
1283
        }
1284
    }
1285
    
1286
    /**
1287
     * Handle the database putdocument request and write an XML document to the
1288
     * database connection
1289
     */
1290
    public String handleInsertOrUpdateAction(String ipAddress,
1291
            HttpServletResponse response, PrintWriter out, Hashtable<String, String[]> params,
1292
            String user, String[] groups) {
1293
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1294
        DBConnection dbConn = null;
1295
        int serialNumber = -1;
1296
        String output = "";
1297
        String qformat = null;
1298
        if(params.containsKey("qformat"))
1299
        {
1300
          qformat = params.get("qformat")[0];
1301
        }
1302
        
1303
        if(params.get("docid") == null){
1304
            String msg = "<?xml version=\"1.0\"?>" +
1305
                "<error>" +
1306
                "Docid not specified" +
1307
                "</error>";
1308
            if(out != null)
1309
            {
1310
                out.println(msg);
1311
                logMetacat.error("MetaCatServlet.handleInsertOrUpdateAction - Docid not specified");
1312
            }
1313
            return msg; 
1314
        }
1315
        
1316
        try {
1317
            if (!AuthUtil.canInsertOrUpdate(user, groups)) {
1318
                String msg = "<?xml version=\"1.0\"?>" +
1319
                "<error>" +
1320
                "User '" + user + "' not allowed to insert and update" +
1321
                "</error>";
1322
                if(out != null)
1323
                {
1324
                  out.println(msg);
1325
                }
1326
                
1327
                logMetacat.error("MetaCatServlet.handleInsertOrUpdateAction - User '" + user + "' not allowed to insert and update");
1328
                return msg;
1329
            }
1330
        } catch (MetacatUtilException ue) {
1331
            logMetacat.error("MetaCatServlet.handleInsertOrUpdateAction - Could not determine if user could insert or update: "
1332
                    + ue.getMessage());
1333
            ue.printStackTrace(System.out);
1334
            // TODO: This is a bug, as it allows one to bypass the access check -- need to throw an exception
1335
        }
1336
        
1337
        try {
1338
            // Get the document indicated
1339
            logMetacat.debug("MetaCatServlet.handleInsertOrUpdateAction - params: " + params.toString());
1340
            
1341
            String[] doctext = params.get("doctext");
1342
            String pub = null;
1343
            if (params.containsKey("public")) {
1344
                pub = params.get("public")[0];
1345
            }
1346
            
1347
            StringReader dtd = null;
1348
            if (params.containsKey("dtdtext")) {
1349
                String[] dtdtext = params.get("dtdtext");
1350
                try {
1351
                    if (!dtdtext[0].equals("")) {
1352
                        dtd = new StringReader(dtdtext[0]);
1353
                    }
1354
                } catch (NullPointerException npe) {
1355
                }
1356
            }
1357
            
1358
            if(doctext == null){
1359
                String msg = "<?xml version=\"1.0\"?>" +
1360
                "<error>" +
1361
                "Document text not submitted." +
1362
                "</error>";
1363
                if(out != null)
1364
                {
1365
                  out.println(msg);
1366
                }
1367
                
1368
                // TODO: this should really throw an exception
1369
                return msg;
1370
            }
1371
            
1372
            logMetacat.debug("MetaCatServlet.handleInsertOrUpdateAction - the xml document in metacat servlet (before parsing):\n" + doctext[0]);
1373
            StringReader xmlReader = new StringReader(doctext[0]);
1374
            boolean validate = false;
1375
            DocumentImplWrapper documentWrapper = null;
1376
            try {
1377
                // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ...
1378
                // >
1379
                // in order to decide whether to use validation parser
1380
                validate = needDTDValidation(xmlReader);
1381
                if (validate) {
1382
                    // set a dtd base validation parser
1383
                    String rule = DocumentImpl.DTD;
1384
                    documentWrapper = new DocumentImplWrapper(rule, validate);
1385
                } else {
1386
                    
1387
                    String namespace = XMLSchemaService.findDocumentNamespace(xmlReader);
1388
                    
1389
                    if (namespace != null) {
1390
                        if (namespace.compareTo(DocumentImpl.EML2_0_0NAMESPACE) == 0
1391
                                || namespace.compareTo(
1392
                                DocumentImpl.EML2_0_1NAMESPACE) == 0) {
1393
                            // set eml2 base     validation parser
1394
                            String rule = DocumentImpl.EML200;
1395
                            // using emlparser to check id validation
1396
                            @SuppressWarnings("unused")
1397
                            EMLParser parser = new EMLParser(doctext[0]);
1398
                            documentWrapper = new DocumentImplWrapper(rule, true);
1399
                        } else if (namespace.compareTo(
1400
                                DocumentImpl.EML2_1_0NAMESPACE) == 0) {
1401
                            // set eml2 base validation parser
1402
                            String rule = DocumentImpl.EML210;
1403
                            // using emlparser to check id validation
1404
                            @SuppressWarnings("unused")
1405
                            EMLParser parser = new EMLParser(doctext[0]);
1406
                            documentWrapper = new DocumentImplWrapper(rule, true);
1407
                        } else {
1408
                            // set schema base validation parser
1409
                            String rule = DocumentImpl.SCHEMA;
1410
                            documentWrapper = new DocumentImplWrapper(rule, true);
1411
                        }
1412
                    } else {
1413
                        documentWrapper = new DocumentImplWrapper("", false);
1414
                    }
1415
                }
1416
                
1417
                String[] action = params.get("action");
1418
                String[] docid = params.get("docid");
1419
                String newdocid = null;
1420
                
1421
                String doAction = null;
1422
                if (action[0].equals("insert") || action[0].equals("insertmultipart")) {
1423
                    doAction = "INSERT";
1424
                } else if (action[0].equals("update")) {
1425
                    doAction = "UPDATE";
1426
                }
1427
                
1428
                try {
1429
                    // get a connection from the pool
1430
                    dbConn = DBConnectionPool
1431
                            .getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1432
                    serialNumber = dbConn.getCheckOutSerialNumber();
1433
                    
1434
                    // write the document to the database and disk
1435
                    String accNumber = docid[0];
1436
                    logMetacat.debug("MetaCatServlet.handleInsertOrUpdateAction - " + doAction + " "
1437
                            + accNumber + "...");
1438
                    if (accNumber == null || accNumber.equals("")) {
1439
                        logMetacat.warn("MetaCatServlet.handleInsertOrUpdateAction - writing with null acnumber");
1440
                        newdocid = documentWrapper.write(dbConn, doctext[0], pub, dtd,
1441
                                doAction, null, user, groups);
1442
                        EventLog.getInstance().log(ipAddress, user, "", action[0]);
1443
                    } else {
1444
                        newdocid = documentWrapper.write(dbConn, doctext[0], pub, dtd,
1445
                                doAction, accNumber, user, groups);
1446

    
1447
                        EventLog.getInstance().log(ipAddress, user, accNumber, action[0]);
1448
                    }
1449
                } finally {
1450
                    // Return db connection
1451
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1452
                }
1453
                
1454
                // set content type and other response header fields first
1455
                //response.setContentType("text/xml");
1456
                output += "<?xml version=\"1.0\"?>";
1457
                output += "<success>";
1458
                output += "<docid>" + newdocid + "</docid>";
1459
                output += "</success>";
1460
                
1461
            } catch (NullPointerException npe) {
1462
                //response.setContentType("text/xml");
1463
                output += "<?xml version=\"1.0\"?>";
1464
                output += "<error>";
1465
                output += npe.getMessage();
1466
                output += "</error>";
1467
                logMetacat.warn("MetaCatServlet.handleInsertOrUpdateAction - Null pointer error when writing eml document to the database: " + npe.getMessage());
1468
                npe.printStackTrace();
1469
            }
1470
        } catch (Exception e) {
1471
            //response.setContentType("text/xml");
1472
            output += "<?xml version=\"1.0\"?>";
1473
            output += "<error>";
1474
            output += e.getMessage();
1475
            output += "</error>";
1476
            logMetacat.warn("MetaCatServlet.handleInsertOrUpdateAction - General error when writing eml document to the database: " + e.getMessage());
1477
            e.printStackTrace();
1478
        }
1479
        
1480
        if (qformat == null || qformat.equals("xml")) {
1481
            if(response != null)
1482
            {
1483
              response.setContentType("text/xml");
1484
              out.println(output);
1485
            }
1486
            return output;
1487
        } else {
1488
            try {
1489
                DBTransform trans = new DBTransform();
1490
                response.setContentType("text/html");
1491
                trans.transformXMLDocument(output,
1492
                        "message", "-//W3C//HTML//EN", qformat,
1493
                        out, null, null);
1494
            } catch (Exception e) {
1495
                
1496
                logMetacat.error("MetaCatServlet.handleInsertOrUpdateAction - General error: "
1497
                        + e.getMessage());
1498
                e.printStackTrace(System.out);
1499
            }
1500
        }
1501
        return null;
1502
    }
1503
    
1504
    /**
1505
     * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > in
1506
     * order to decide whether to use validation parser
1507
     */
1508
    private static boolean needDTDValidation(StringReader xmlreader)
1509
    throws IOException {
1510
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1511
        StringBuffer cbuff = new StringBuffer();
1512
        java.util.Stack<String> st = new java.util.Stack<String>();
1513
        boolean validate = false;
1514
        boolean commented = false;
1515
        int c;
1516
        int inx;
1517
        
1518
        // read from the stream until find the keywords
1519
        while ((st.empty() || st.size() < 4) && ((c = xmlreader.read()) != -1)) {
1520
            cbuff.append((char) c);
1521
            
1522
            if ((inx = cbuff.toString().indexOf("<!--")) != -1) {
1523
                commented = true;
1524
            }
1525
            
1526
            // "<!DOCTYPE" keyword is found; put it in the stack
1527
            if ((inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1) {
1528
                cbuff = new StringBuffer();
1529
                st.push("<!DOCTYPE");
1530
            }
1531
            // "PUBLIC" keyword is found; put it in the stack
1532
            if ((inx = cbuff.toString().indexOf("PUBLIC")) != -1) {
1533
                cbuff = new StringBuffer();
1534
                st.push("PUBLIC");
1535
            }
1536
            // "SYSTEM" keyword is found; put it in the stack
1537
            if ((inx = cbuff.toString().indexOf("SYSTEM")) != -1) {
1538
                cbuff = new StringBuffer();
1539
                st.push("SYSTEM");
1540
            }
1541
            // ">" character is found; put it in the stack
1542
            // ">" is found twice: fisrt from <?xml ...?>
1543
            // and second from <!DOCTYPE ... >
1544
            if ((inx = cbuff.toString().indexOf(">")) != -1) {
1545
                cbuff = new StringBuffer();
1546
                st.push(">");
1547
            }
1548
        }
1549
        
1550
        // close the stream
1551
        xmlreader.reset();
1552
        
1553
        // check the stack whether it contains the keywords:
1554
        // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1555
        if (st.size() == 4) {
1556
            if ((st.pop()).equals(">")
1557
            && ((st.peek()).equals("PUBLIC") | (st.pop()).equals("SYSTEM"))
1558
                    && (st.pop()).equals("<!DOCTYPE")) {
1559
                validate = true && !commented;
1560
            }
1561
        }
1562
        
1563
        logMetacat.info("MetaCatServlet.needDTDValidation - Validation for dtd is " + validate);
1564
        return validate;
1565
    }
1566
    
1567
    // END OF INSERT/UPDATE SECTION
1568
    
1569
    /**
1570
     * Handle the database delete request and delete an XML document from the
1571
     * database connection
1572
     */
1573
    public void handleDeleteAction(PrintWriter out, Hashtable<String, String[]> params,
1574
            HttpServletRequest request, HttpServletResponse response,
1575
            String user, String[] groups) {
1576
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1577
        String[] docid = params.get("docid");
1578
        
1579
        if(docid == null){
1580
            response.setContentType("text/xml");
1581
            out.println("<?xml version=\"1.0\"?>");
1582
            out.println("<error>");
1583
            out.println("Docid not specified.");
1584
            out.println("</error>");
1585
            logMetacat.error("MetaCatServlet.handleDeleteAction - Docid not specified for the document to be deleted.");
1586
        } else {
1587
            
1588
            // delete the document from the database
1589
            try {
1590
                
1591
                try {
1592
                    // null means notify server is null
1593
                    DocumentImpl.delete(docid[0], user, groups, null);
1594
                    EventLog.getInstance().log(request.getRemoteAddr(),
1595
                            user, docid[0], "delete");
1596
                    response.setContentType("text/xml");
1597
                    out.println("<?xml version=\"1.0\"?>");
1598
                    out.println("<success>");
1599
                    out.println("Document deleted.");
1600
                    out.println("</success>");
1601
                    logMetacat.info("MetaCatServlet.handleDeleteAction - Document deleted.");
1602
                    
1603
                    // Delete from spatial cache if runningSpatialOption
1604
                    if ( PropertyService.getProperty("spatial.runSpatialOption").equals("true") ) {
1605
                        SpatialHarvester sh = new SpatialHarvester();
1606
                        sh.addToDeleteQue( DocumentUtil.getSmartDocId( docid[0] ) );
1607
                        sh.destroy();
1608
                    }
1609
                    
1610
                } catch (AccessionNumberException ane) {
1611
                    response.setContentType("text/xml");
1612
                    out.println("<?xml version=\"1.0\"?>");
1613
                    out.println("<error>");
1614
                    //out.println("Error deleting document!!!");
1615
                    out.println(ane.getMessage());
1616
                    out.println("</error>");
1617
                    logMetacat.error("MetaCatServlet.handleDeleteAction - Document could not be deleted: "
1618
                            + ane.getMessage());
1619
                    ane.printStackTrace(System.out);
1620
                }
1621
            } catch (Exception e) {
1622
                response.setContentType("text/xml");
1623
                out.println("<?xml version=\"1.0\"?>");
1624
                out.println("<error>");
1625
                out.println(e.getMessage());
1626
                out.println("</error>");
1627
                logMetacat.error("MetaCatServlet.handleDeleteAction - Document could not be deleted: "
1628
                        + e.getMessage());
1629
                e.printStackTrace(System.out);
1630
            }
1631
        }
1632
    }
1633
    
1634
    /**
1635
     * Handle the validation request and return the results to the requestor
1636
     */
1637
    protected void handleValidateAction(PrintWriter out, Hashtable<String, String[]> params) {
1638
        
1639
        // Get the document indicated
1640
        String valtext = null;
1641
        DBConnection dbConn = null;
1642
        int serialNumber = -1;
1643
        
1644
        try {
1645
            valtext = params.get("valtext")[0];
1646
        } catch (Exception nullpe) {
1647
            
1648
            String docid = null;
1649
            try {
1650
                // Find the document id number
1651
                docid = params.get("docid")[0];
1652
                
1653
                // Get the document indicated from the db
1654
                DocumentImpl xmldoc = new DocumentImpl(docid);
1655
                valtext = xmldoc.toString();
1656
                
1657
            } catch (NullPointerException npe) {
1658
                
1659
                out.println("<error>Error getting document ID: " + docid
1660
                        + "</error>");
1661
                //if ( conn != null ) { util.returnConnection(conn); }
1662
                return;
1663
            } catch (Exception e) {
1664
                
1665
                out.println(e.getMessage());
1666
            }
1667
        }
1668
        
1669
        try {
1670
            // get a connection from the pool
1671
            dbConn = DBConnectionPool
1672
                    .getDBConnection("MetaCatServlet.handleValidateAction");
1673
            serialNumber = dbConn.getCheckOutSerialNumber();
1674
            DBValidate valobj = new DBValidate(dbConn);
1675
//            boolean valid = valobj.validateString(valtext);
1676
            
1677
            // set content type and other response header fields first
1678
            
1679
            out.println(valobj.returnErrors());
1680
            
1681
        } catch (NullPointerException npe2) {
1682
            // set content type and other response header fields first
1683
            
1684
            out.println("<error>Error validating document.</error>");
1685
        } catch (Exception e) {
1686
            
1687
            out.println(e.getMessage());
1688
        } finally {
1689
            // Return db connection
1690
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1691
        }
1692
    }
1693
    
1694
    /**
1695
     * Handle "getrevsionanddoctype" action Given a docid, return it's current
1696
     * revision and doctype from data base The output is String look like
1697
     * "rev;doctype"
1698
     */
1699
    protected void handleGetRevisionAndDocTypeAction(PrintWriter out,
1700
            Hashtable<String, String[]> params) {
1701
        // To store doc parameter
1702
        String[] docs = new String[10];
1703
        // Store a single doc id
1704
        String givenDocId = null;
1705
        // Get docid from parameters
1706
        if (params.containsKey("docid")) {
1707
            docs = params.get("docid");
1708
        }
1709
        // Get first docid form string array
1710
        givenDocId = docs[0];
1711
        
1712
        try {
1713
            // Make sure there is a docid
1714
            if (givenDocId == null || givenDocId.equals("")) { throw new Exception(
1715
                    "User didn't specify docid!"); }//if
1716
            
1717
            // Create a DBUtil object
1718
            DBUtil dbutil = new DBUtil();
1719
            // Get a rev and doctype
1720
            String revAndDocType = dbutil
1721
                    .getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
1722
            out.println(revAndDocType);
1723
            
1724
        } catch (Exception e) {
1725
            // Handle exception
1726
            out.println("<?xml version=\"1.0\"?>");
1727
            out.println("<error>");
1728
            out.println(e.getMessage());
1729
            out.println("</error>");
1730
        }
1731
        
1732
    }
1733
    
1734
    /**
1735
     * Handle "getaccesscontrol" action. Read Access Control List from db
1736
     * connection in XML format
1737
     */
1738
    protected void handleGetAccessControlAction(PrintWriter out,
1739
            Hashtable<String,String[]> params, HttpServletResponse response, String username,
1740
            String[] groupnames) {
1741
        
1742
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1743

    
1744
        String docid = params.get("docid")[0];
1745
        if (docid.startsWith("urn:")) {
1746
            try {
1747
                String actualDocId = LSIDUtil.getDocId(docid, false);
1748
                docid = actualDocId;
1749
            } catch (ParseLSIDException ple) {
1750
                logMetacat.error("MetaCatServlet.handleGetAccessControlAction - MetaCatServlet.handleGetAccessControlAction - " +
1751
                        "could not parse lsid: " + docid + " : " + ple.getMessage());  
1752
                ple.printStackTrace(System.out);
1753
            }
1754
        }
1755
        
1756
        String qformat = "xml";
1757
        if (params.get("qformat") != null) {
1758
            qformat = (params.get("qformat"))[0];
1759
        }
1760
        
1761
        try {
1762
            AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
1763
            String acltext = acfsf.getACL(username, groupnames);
1764
            if (qformat.equals("xml")) {
1765
                response.setContentType("text/xml");
1766
                out.println(acltext);
1767
            } else {
1768
                DBTransform trans = new DBTransform();
1769
                response.setContentType("text/html");
1770
                trans.transformXMLDocument(acltext,"-//NCEAS//getaccesscontrol//EN", 
1771
                    "-//W3C//HTML//EN", qformat, out, params, null);              
1772
            }            
1773
        } catch (Exception e) {
1774
            out.println("<?xml version=\"1.0\"?>");
1775
            out.println("<error>");
1776
            out.println(e.getMessage());
1777
            out.println("</error>");
1778
        } 
1779
//        finally {
1780
//            // Retrun db connection to pool
1781
//            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1782
//        }
1783
    }
1784
    
1785
    /**
1786
     * Handle the "getprincipals" action. Read all principals from
1787
     * authentication scheme in XML format
1788
     */
1789
    protected void handleGetPrincipalsAction(PrintWriter out, String user,
1790
            String password) {
1791
        try {
1792
            AuthSession auth = new AuthSession();
1793
            String principals = auth.getPrincipals(user, password);
1794
            out.println(principals);
1795
            
1796
        } catch (Exception e) {
1797
            out.println("<?xml version=\"1.0\"?>");
1798
            out.println("<error>");
1799
            out.println(e.getMessage());
1800
            out.println("</error>");
1801
        }
1802
    }
1803
    
1804
    /**
1805
     * Handle "getdoctypes" action. Read all doctypes from db connection in XML
1806
     * format
1807
     */
1808
    protected void handleGetDoctypesAction(PrintWriter out, Hashtable<String, String[]> params,
1809
            HttpServletResponse response) {
1810
        try {
1811
            DBUtil dbutil = new DBUtil();
1812
            String doctypes = dbutil.readDoctypes();
1813
            out.println(doctypes);
1814
        } catch (Exception e) {
1815
            out.println("<?xml version=\"1.0\"?>");
1816
            out.println("<error>");
1817
            out.println(e.getMessage());
1818
            out.println("</error>");
1819
        }
1820
    }
1821
    
1822
    /**
1823
     * Handle the "getdtdschema" action. Read DTD or Schema file for a given
1824
     * doctype from Metacat catalog system
1825
     */
1826
    protected void handleGetDTDSchemaAction(PrintWriter out, Hashtable<String, String[]> params,
1827
            HttpServletResponse response) {
1828
        
1829
        String doctype = null;
1830
        String[] doctypeArr = params.get("doctype");
1831
        
1832
        // get only the first doctype specified in the list of doctypes
1833
        // it could be done for all doctypes in that list
1834
        if (doctypeArr != null) {
1835
            doctype = params.get("doctype")[0];
1836
        }
1837
        
1838
        try {
1839
            DBUtil dbutil = new DBUtil();
1840
            String dtdschema = dbutil.readDTDSchema(doctype);
1841
            out.println(dtdschema);
1842
            
1843
        } catch (Exception e) {
1844
            out.println("<?xml version=\"1.0\"?>");
1845
            out.println("<error>");
1846
            out.println(e.getMessage());
1847
            out.println("</error>");
1848
        }
1849
        
1850
    }
1851
    
1852
    /**
1853
     * Check if the document is registered in either the xml_documents or xml_revisions table
1854
     * @param out the writer to write the xml results to
1855
     * @param params request parameters
1856
     * @param response the http servlet response
1857
     */
1858
    public void handleIdIsRegisteredAction(PrintWriter out, Hashtable<String, String[]> params,
1859
            HttpServletResponse response) {
1860
        String id = null;
1861
        boolean exists = false;
1862
        if(params.get("docid") != null) {
1863
            id = params.get("docid")[0];
1864
        }
1865
        
1866
        try {
1867
            DBUtil dbutil = new DBUtil();
1868
            exists = dbutil.idExists(id);
1869
        } catch (Exception e) {
1870
            out.println("<?xml version=\"1.0\"?>");
1871
            out.println("<error>");
1872
            out.println(e.getMessage());
1873
            out.println("</error>");
1874
        }
1875
        
1876
        out.println("<?xml version=\"1.0\"?>");
1877
        out.println("<isRegistered>");
1878
        out.println("<docid>" + id + "</docid>");
1879
        out.println("<exists>" + exists + "</exists>");
1880
        out.println("</isRegistered>");
1881
    }
1882
    
1883
    /**
1884
     * Handle the "getalldocids" action. return a list of all docids registered
1885
     * in the system
1886
     */
1887
    public void handleGetAllDocidsAction(PrintWriter out, Hashtable<String, String[]> params,
1888
            HttpServletResponse response) {
1889
        String scope = null;
1890
        if(params.get("scope") != null) {
1891
            scope = params.get("scope")[0];
1892
        }
1893
        
1894
        try {
1895
            DBUtil dbutil = new DBUtil();
1896
            Vector<String> docids = dbutil.getAllDocids(scope);
1897
            out.println("<?xml version=\"1.0\"?>");
1898
            out.println("<idList>");
1899
            out.println("  <scope>" + scope + "</scope>");
1900
            for(int i=0; i<docids.size(); i++) {
1901
                String docid = docids.elementAt(i);
1902
                out.println("  <docid>" + docid + "</docid>");
1903
            }
1904
            out.println("</idList>");
1905
            
1906
        } catch (Exception e) {
1907
            out.println("<?xml version=\"1.0\"?>");
1908
            out.println("<error>");
1909
            out.println(e.getMessage());
1910
            out.println("</error>");
1911
        }
1912
    }
1913
    
1914
    /**
1915
     * Handle the "getlastdocid" action. Get the latest docid with rev number
1916
     * from db connection in XML format
1917
     */
1918
    public void handleGetMaxDocidAction(PrintWriter out, Hashtable<String, String[]> params,
1919
            HttpServletResponse response) {
1920
        
1921
        String scope = params.get("scope")[0];
1922
        if (scope == null) {
1923
            scope = params.get("username")[0];
1924
        }
1925
        
1926
        try {
1927
            
1928
            DBUtil dbutil = new DBUtil();
1929
            String lastDocid = dbutil.getMaxDocid(scope);
1930
            out.println("<?xml version=\"1.0\"?>");
1931
            out.println("<lastDocid>");
1932
            out.println("  <scope>" + scope + "</scope>");
1933
            out.println("  <docid>" + lastDocid + "</docid>");
1934
            out.println("</lastDocid>");
1935
            
1936
        } catch (Exception e) {
1937
            out.println("<?xml version=\"1.0\"?>");
1938
            out.println("<error>");
1939
            out.println(e.getMessage());
1940
            out.println("</error>");
1941
        }
1942
    }
1943
    
1944
    /**
1945
     * Print a report from the event log based on filter parameters passed in
1946
     * from the web.
1947
     *
1948
     * @param params the parameters from the web request
1949
     * @param request the http request object for getting request details
1950
     * @param response the http response object for writing output
1951
     */
1952
    protected void handleGetLogAction(Hashtable<String, String[]> params, HttpServletRequest request,
1953
            HttpServletResponse response, String username, String[] groups) {
1954
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1955
        try {
1956
            response.setContentType("text/xml");
1957
            PrintWriter out = response.getWriter();
1958
            
1959
            // Check that the user is authenticated as an administrator account
1960
            if (!AuthUtil.isAdministrator(username, groups)) {
1961
                out.print("<error>");
1962
                out.print("The user \"" + username +
1963
                        "\" is not authorized for this action.");
1964
                out.print("</error>");
1965
                return;
1966
            }
1967
            
1968
            // Get all of the parameters in the correct formats
1969
            String[] ipAddress = params.get("ipaddress");
1970
            String[] principal = params.get("principal");
1971
            String[] docid = params.get("docid");
1972
            String[] event = params.get("event");
1973
            String[] startArray = params.get("start");
1974
            String[] endArray = params.get("end");
1975
            String start = null;
1976
            String end = null;
1977
            if (startArray != null) {
1978
                start = startArray[0];
1979
            }
1980
            if (endArray != null) {
1981
                end = endArray[0];
1982
            }
1983
            Timestamp startDate = null;
1984
            Timestamp endDate = null;
1985
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
1986
            try {
1987
                if (start != null) {
1988
                    startDate = new Timestamp((format.parse(start)).getTime());
1989
                }
1990
                if (end != null) {
1991
                    endDate = new Timestamp((format.parse(end)).getTime());
1992
                }
1993
            } catch (ParseException e) {
1994
                logMetacat.error("MetaCatServlet.handleGetLogAction - Failed to created Timestamp from input.");
1995
                e.printStackTrace(System.out);
1996
            }
1997
            
1998
            // Request the report by passing the filter parameters
1999
            out.println(EventLog.getInstance().getReport(ipAddress, principal,
2000
                    docid, event, startDate, endDate));
2001
            out.close();
2002
        } catch (IOException e) {
2003
            logMetacat.error("MetaCatServlet.handleGetLogAction - Could not open http response for writing: "
2004
                    + e.getMessage());
2005
            e.printStackTrace(System.out);
2006
        } catch (MetacatUtilException ue) {
2007
            logMetacat.error("MetaCatServlet.handleGetLogAction - Could not determine if user is administrator: "
2008
                    + ue.getMessage());
2009
            ue.printStackTrace(System.out);
2010
        }
2011
    }
2012
    
2013
    /**
2014
     * Rebuild the index for one or more documents. If the docid parameter is
2015
     * provided, rebuild for just that one document or list of documents. If
2016
     * not, then rebuild the index for all documents in the xml_documents table.
2017
     * 
2018
     * @param params
2019
     *            the parameters from the web request
2020
     * @param request
2021
     *            the http request object for getting request details
2022
     * @param response
2023
     *            the http response object for writing output
2024
     * @param username
2025
     *            the username of the authenticated user
2026
     */
2027
    protected void handleBuildIndexAction(Hashtable<String, String[]> params,
2028
            HttpServletRequest request, HttpServletResponse response,
2029
            String username, String[] groups) {
2030
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2031
        
2032
        // Get all of the parameters in the correct formats
2033
        String[] docid = params.get("docid");
2034
        
2035
        // Rebuild the indices for appropriate documents
2036
        try {
2037
            response.setContentType("text/xml");
2038
            PrintWriter out = response.getWriter();
2039
            
2040
            // Check that the user is authenticated as an administrator account
2041
            if (!AuthUtil.isAdministrator(username, groups)) {
2042
                out.print("<error>");
2043
                out.print("The user \"" + username +
2044
                        "\" is not authorized for this action.");
2045
                out.print("</error>");
2046
                return;
2047
            }
2048
            
2049
            // Process the documents
2050
            out.println("<success>");
2051
            if (docid == null || docid.length == 0) {
2052
                // Process all of the documents
2053
                try {
2054
                    Vector<String> documents = getDocumentList();
2055
                    Iterator<String> it = documents.iterator();
2056
                    while (it.hasNext()) {
2057
                        String id = it.next();
2058
                        buildDocumentIndex(id, out);
2059
                    }
2060
                } catch (SQLException se) {
2061
                    out.print("<error>");
2062
                    out.print(se.getMessage());
2063
                    out.println("</error>");
2064
                }
2065
            } else {
2066
                // Only process the requested documents
2067
                for (int i = 0; i < docid.length; i++) {
2068
                    buildDocumentIndex(docid[i], out);
2069
                }
2070
            }
2071
            out.println("</success>");
2072
            out.close();
2073
        } catch (IOException e) {
2074
            logMetacat.error("MetaCatServlet.handleBuildIndexAction - Could not open http response for writing: "
2075
                    + e.getMessage());
2076
            e.printStackTrace(System.out);
2077
        } catch (MetacatUtilException ue) {
2078
            logMetacat.error("MetaCatServlet.handleBuildIndexAction - Could not determine if user is administrator: "
2079
                    + ue.getMessage());
2080
            ue.printStackTrace(System.out);
2081
        }
2082
    }
2083
    
2084
    /**
2085
     * Build the index for one document by reading the document and
2086
     * calling its buildIndex() method.
2087
     *
2088
     * @param docid the document (with revision) to rebuild
2089
     * @param out the PrintWriter to which output is printed
2090
     */
2091
    private void buildDocumentIndex(String docid, PrintWriter out) {
2092
        try {
2093
            DocumentImpl doc = new DocumentImpl(docid, false);
2094
            doc.buildIndex();
2095
            out.print("<docid>" + docid);
2096
            out.println("</docid>");
2097
        } catch (McdbException me) {
2098
            out.print("<error>");
2099
            out.print(me.getMessage());
2100
            out.println("</error>");
2101
        }
2102
    }
2103
    
2104
    /**
2105
     * Handle documents passed to metacat that are encoded using the
2106
     * "multipart/form-data" mime type. This is typically used for uploading
2107
     * data files which may be binary and large.
2108
     */
2109
    protected void handleMultipartForm(HttpServletRequest request,
2110
            HttpServletResponse response) {
2111
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2112
        PrintWriter out = null;
2113
        String action = null;
2114
        
2115
        // Parse the multipart form, and save the parameters in a Hashtable and
2116
        // save the FileParts in a hashtable
2117
        
2118
        Hashtable<String,String[]> params = new Hashtable<String,String[]>();
2119
        Hashtable<String,String> fileList = new Hashtable<String,String>();
2120
        int sizeLimit = 1000;
2121
        try {
2122
            sizeLimit = 
2123
                (new Integer(PropertyService.getProperty("replication.datafilesizelimit"))).intValue();
2124
        } catch (PropertyNotFoundException pnfe) {
2125
            logMetacat.error("MetaCatServlet.handleMultipartForm - Could not determine data file size limit.  Using 1000. " 
2126
                    + pnfe.getMessage());
2127
            pnfe.printStackTrace(System.out);
2128
        }
2129
        logMetacat.debug("MetaCatServlet.handleMultipartForm - The size limit of uploaded data files is: " + sizeLimit);
2130
        
2131
        try {
2132
            MultipartParser mp = new MultipartParser(request,
2133
                    sizeLimit * 1024 * 1024);
2134
            Part part;
2135
            
2136
            while ((part = mp.readNextPart()) != null) {
2137
                String name = part.getName();
2138
                
2139
                if (part.isParam()) {
2140
                    // it's a parameter part
2141
                    ParamPart paramPart = (ParamPart) part;
2142
                    String[] values = new String[1];
2143
                    values[0] = paramPart.getStringValue();
2144
                    params.put(name, values);
2145
                    if (name.equals("action")) {
2146
                        action = values[0];
2147
                    }
2148
                } else if (part.isFile()) {
2149
                    // it's a file part
2150
                    FilePart filePart = (FilePart) part;
2151
                    String fileName = filePart.getFileName();
2152
                    String fileTempLocation;
2153
                    
2154
                    // the filePart will be clobbered on the next loop, save to disk
2155
                    fileTempLocation = MetacatUtil.writeTempUploadFile(filePart, fileName);
2156
                    fileList.put(name, fileTempLocation);
2157
                    fileList.put("filename", fileName);
2158
                    fileList.put("name", fileTempLocation);
2159
                } else {
2160
                    logMetacat.info("MetaCatServlet.handleMultipartForm - Upload name '" + name + "' was empty.");
2161
                }
2162
            }
2163
        } catch (IOException ioe) {
2164
            try {
2165
                out = response.getWriter();
2166
            } catch (IOException ioe2) {
2167
                logMetacat.fatal("MetaCatServlet.handleMultipartForm - Fatal Error: couldn't get response output stream.");
2168
            }
2169
            out.println("<?xml version=\"1.0\"?>");
2170
            out.println("<error>");
2171
            out.println("Error: problem reading multipart data: " + ioe.getMessage());
2172
            out.println("</error>");
2173
            out.close();
2174
            return;
2175
        }
2176
        
2177
        // Get the session information
2178
        String username = null;
2179
        String password = null;
2180
        String[] groupnames = null;
2181
        String sess_id = null;
2182
        
2183
        // be aware of session expiration on every request
2184
        HttpSession sess = request.getSession(true);
2185
        if (sess.isNew()) {
2186
            // session expired or has not been stored b/w user requests
2187
            username = "public";
2188
            sess.setAttribute("username", username);
2189
        } else {
2190
            username = (String) sess.getAttribute("username");
2191
            password = (String) sess.getAttribute("password");
2192
            groupnames = (String[]) sess.getAttribute("groupnames");
2193
            try {
2194
                sess_id = (String) sess.getId();
2195
            } catch (IllegalStateException ise) {
2196
                System.out
2197
                        .println("error in  handleMultipartForm: this shouldn't "
2198
                        + "happen: the session should be valid: "
2199
                        + ise.getMessage());
2200
            }
2201
        }
2202
        
2203
        // Get the out stream
2204
        try {
2205
            out = response.getWriter();
2206
        } catch (IOException ioe2) {
2207
            logMetacat.error("MetaCatServlet.handleMultipartForm - Fatal Error: couldn't get response "
2208
                    + "output stream.");
2209
            ioe2.printStackTrace(System.out);
2210
        }
2211
        
2212
        if (action.equals("upload")) {
2213
            if (username != null && !username.equals("public")) {
2214
                handleUploadAction(request, out, params, fileList, username,
2215
                        groupnames, response);
2216
            } else {                
2217
                out.println("<?xml version=\"1.0\"?>");
2218
                out.println("<error>");
2219
                out.println("Permission denied for " + action);
2220
                out.println("</error>");
2221
            }
2222
        } else if(action.equals("insertmultipart")) {
2223
          if (username != null && !username.equals("public")) {
2224
            logMetacat.debug("MetaCatServlet.handleMultipartForm - handling multipart insert");
2225
              handleInsertMultipartAction(request, response,
2226
                            out, params, fileList, username, groupnames);
2227
          } else {
2228
              out.println("<?xml version=\"1.0\"?>");
2229
              out.println("<error>");
2230
              out.println("Permission denied for " + action);
2231
              out.println("</error>");
2232
          }
2233
        } else {
2234
            /*
2235
             * try { out = response.getWriter(); } catch (IOException ioe2) {
2236
             * System.err.println("Fatal Error: couldn't get response output
2237
             * stream.");
2238
             */
2239
            out.println("<?xml version=\"1.0\"?>");
2240
            out.println("<error>");
2241
            out.println("Error: action not registered.  Please report this error.");
2242
            out.println("</error>");
2243
        }
2244
        out.close();
2245
    }
2246
    
2247
    /**
2248
     * Handle the upload action by saving the attached file to disk and
2249
     * registering it in the Metacat db
2250
     */
2251
    private void handleInsertMultipartAction(HttpServletRequest request, 
2252
            HttpServletResponse response,
2253
            PrintWriter out, Hashtable<String,String[]> params, Hashtable<String,String> fileList,
2254
            String username, String[] groupnames)
2255
    {
2256
      Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2257
      String action = null;
2258
      String docid = null;
2259
      String qformat = null;
2260
      String output = "";
2261
      
2262
      /*
2263
       * response.setContentType("text/xml"); try { out =
2264
       * response.getWriter(); } catch (IOException ioe2) {
2265
       * System.err.println("Fatal Error: couldn't get response output
2266
       * stream.");
2267
       */
2268
      
2269
      if (params.containsKey("docid")) 
2270
      {
2271
          docid = params.get("docid")[0];
2272
      }
2273
      
2274
      if(params.containsKey("qformat")) 
2275
      {
2276
          qformat = params.get("qformat")[0];
2277
      }
2278
      
2279
      // Make sure we have a docid and datafile
2280
      if (docid != null && fileList.containsKey("datafile")) 
2281
      {
2282
        logMetacat.info("MetaCatServlet.handleInsertMultipartAction - Uploading data docid: " + docid);
2283
        // Get a reference to the file part of the form
2284
        //FilePart filePart = (FilePart) fileList.get("datafile");
2285
        String fileName = fileList.get("filename");
2286
        logMetacat.debug("MetaCatServlet.handleInsertMultipartAction - Uploading filename: " + fileName);
2287
        // Check if the right file existed in the uploaded data
2288
        if (fileName != null) 
2289
        {
2290
              
2291
          try 
2292
          {
2293
              //logMetacat.info("Upload datafile " + docid
2294
              // +"...", 10);
2295
              //If document get lock data file grant
2296
            if (DocumentImpl.getDataFileLockGrant(docid)) 
2297
            {
2298
              // Save the data file to disk using "docid" as the name
2299
              String datafilepath = PropertyService.getProperty("application.datafilepath");
2300
              File dataDirectory = new File(datafilepath);
2301
              dataDirectory.mkdirs();
2302
              File newFile = null;
2303
    //          File tempFile = null;
2304
              String tempFileName = fileList.get("name");
2305
              String newFileName = dataDirectory + File.separator + docid;
2306
              long size = 0;
2307
              boolean fileExists = false;
2308
                      
2309
              try 
2310
              {
2311
                newFile = new File(newFileName);
2312
                fileExists = newFile.exists();
2313
                logMetacat.info("MetaCatServlet.handleInsertMultipartAction - new file status is: " + fileExists);
2314
                if(fileExists)
2315
                {
2316
                  newFile.delete();
2317
                  newFile.createNewFile();
2318
                  fileExists = false;
2319
                }
2320
                
2321
                if ( fileExists == false ) 
2322
                {
2323
                    // copy file to desired output location
2324
                    try 
2325
                    {
2326
                        MetacatUtil.copyFile(tempFileName, newFileName);
2327
                    } 
2328
                    catch (IOException ioe) 
2329
                    {
2330
                        logMetacat.error("MetaCatServlet.handleInsertMultipartAction - IO Exception copying file: " +
2331
                                ioe.getMessage());
2332
                        ioe.printStackTrace(System.out);
2333
                    }
2334
                    size = newFile.length();
2335
                    if (size == 0) 
2336
                    {
2337
                        throw new IOException("MetaCatServlet.handleInsertMultipartAction - Uploaded file is 0 bytes!");
2338
                    }
2339
                }
2340
                logMetacat.info("MetaCatServlet.handleInsertMultipartAction - Uploading the following to Metacat:" +
2341
                        fileName + ", " + docid + ", " +
2342
                        username + ", " + groupnames);
2343
                FileReader fr = new FileReader(newFile);
2344
                
2345
                char[] c = new char[1024];
2346
                int numread = fr.read(c, 0, 1024);
2347
                StringBuffer sb = new StringBuffer();
2348
                while(numread != -1)
2349
                {
2350
                  sb.append(c, 0, numread);
2351
                  numread = fr.read(c, 0, 1024);
2352
                }
2353
                
2354
                Enumeration<String> keys = params.keys();
2355
                while(keys.hasMoreElements())
2356
                { //convert the params to arrays
2357
                  String key = keys.nextElement();
2358
                  String[] paramValue = params.get(key);
2359
                  String[] s = new String[1];
2360
                  s[0] = paramValue[0];
2361
                  params.put(key, s);
2362
                }
2363
                //add the doctext to the params
2364
                String doctext = sb.toString();
2365
                String[] doctextArr = new String[1];
2366
                doctextArr[0] = doctext;
2367
                params.put("doctext", doctextArr);
2368
                //call the insert routine
2369
                handleInsertOrUpdateAction(request.getRemoteAddr(), response, out, 
2370
                          params, username, groupnames);
2371
              }
2372
              catch(Exception e)
2373
              {
2374
                throw e;
2375
              }
2376
            }
2377
          }
2378
          catch(Exception e)
2379
          {
2380
              logMetacat.error("MetaCatServlet.handleInsertMultipartAction - error uploading text file via multipart: " + e.getMessage());
2381
              e.printStackTrace(System.out);;
2382
          }
2383
        }
2384
      }
2385
    }
2386
    
2387
    /**
2388
     * Handle the upload action by saving the attached file to disk and
2389
     * registering it in the Metacat db
2390
     */
2391
    private void handleUploadAction(HttpServletRequest request,
2392
            PrintWriter out, Hashtable<String, String[]> params, Hashtable<String,String> fileList,
2393
            String username, String[] groupnames, HttpServletResponse response) {
2394
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2395
        //PrintWriter out = null;
2396
        //Connection conn = null;
2397
        //        String action = null;
2398
        String docid = null;
2399
        String qformat = null;
2400
        String output = "";
2401

    
2402
        /*
2403
         * response.setContentType("text/xml"); try { out =
2404
         * response.getWriter(); } catch (IOException ioe2) {
2405
         * System.err.println("Fatal Error: couldn't get response output
2406
         * stream.");
2407
         */
2408

    
2409
        if (params.containsKey("docid")) {
2410
            docid = params.get("docid")[0];
2411
        }
2412

    
2413
        if(params.containsKey("qformat")) {
2414
            qformat = params.get("qformat")[0];
2415
        }
2416

    
2417
        // Make sure we have a docid and datafile
2418
        if (docid != null && fileList.containsKey("datafile")) {
2419
            logMetacat.info("MetaCatServlet.handleUploadAction - Uploading data docid: " + docid);
2420
            // Get a reference to the file part of the form
2421
            //FilePart filePart = (FilePart) fileList.get("datafile");
2422
            String fileName = fileList.get("filename");
2423
            logMetacat.info("MetaCatServlet.handleUploadAction - Uploading filename: " + fileName);
2424
            // Check if the right file existed in the uploaded data
2425
            if (fileName != null) {
2426

    
2427
                try {
2428
                    //logMetacat.info("Upload datafile " + docid
2429
                    // +"...", 10);
2430
                    //If document get lock data file grant
2431
                    if (DocumentImpl.getDataFileLockGrant(docid)) {
2432
                        // Save the data file to disk using "docid" as the name
2433
                        String datafilepath = PropertyService.getProperty("application.datafilepath");
2434
                        File dataDirectory = new File(datafilepath);
2435
                        dataDirectory.mkdirs();
2436
                        File newFile = null;
2437
                        //                    File tempFile = null;
2438
                        String tempFileName = fileList.get("name");
2439
                        String newFileName = dataDirectory + File.separator + docid;
2440
                        long size = 0;
2441
                        boolean fileExists = false;
2442

    
2443
                        try {
2444
                            newFile = new File(newFileName);
2445
                            fileExists = newFile.exists();
2446
                            logMetacat.info("MetaCatServlet.handleUploadAction - new file status is: " + fileExists);
2447
                            if ( fileExists == false ) {
2448
                                // copy file to desired output location
2449
                                try {
2450
                                    MetacatUtil.copyFile(tempFileName, newFileName);
2451
                                } catch (IOException ioe) {
2452
                                    logMetacat.error("IO Exception copying file: " +
2453
                                            ioe.getMessage());
2454
                                    ioe.printStackTrace(System.out);
2455
                                }
2456
                                size = newFile.length();
2457
                                if (size == 0) {
2458
                                    throw new IOException("Uploaded file is 0 bytes!");
2459
                                }
2460
                            } // Latent bug here if the file already exists, then the
2461
                              // conditional fails but the document is still registered.
2462
                              // maybe this never happens because we already requested a lock?
2463
                            logMetacat.info("MetaCatServlet.handleUploadAction - Uploading the following to Metacat:" +
2464
                                    fileName + ", " + docid + ", " +
2465
                                    username + ", " + groupnames);
2466
                            //register the file in the database (which generates
2467
                            // an exception
2468
                            //if the docid is not acceptable or other untoward
2469
                            // things happen
2470
                            DocumentImpl.registerDocument(fileName, "BIN", docid,
2471
                                    username, groupnames);
2472
                        } catch (Exception ee) {
2473
                            // If the file did not exist before this method was 
2474
                            // called and an exception is generated while 
2475
                            // creating or registering it, then we want to delete
2476
                            // the file from disk because the operation failed.
2477
                            // However, if the file already existed before the 
2478
                            // method was called, then the exception probably
2479
                            // occurs when registering the document, and so we
2480
                            // want to leave the old file in place.
2481
                            if ( fileExists == false ) {
2482
                                newFile.delete();
2483
                            }
2484
                            
2485
                            logMetacat.info("MetaCatServlet.handleUploadAction - in Exception: fileExists is " + fileExists);
2486
                            logMetacat.error("MetaCatServlet.handleUploadAction - Upload Error: " + ee.getMessage());
2487
                            throw ee;
2488
                        }
2489

    
2490
                        EventLog.getInstance().log(request.getRemoteAddr(),
2491
                                username, docid, "upload");
2492
                        // Force replication this data file
2493
                        // To data file, "insert" and update is same
2494
                        // The fourth parameter is null. Because it is
2495
                        // notification server
2496
                        // and this method is in MetaCatServerlet. It is
2497
                        // original command,
2498
                        // not get force replication info from another metacat
2499
                        ForceReplicationHandler frh = new ForceReplicationHandler(
2500
                                docid, "insert", false, null);
2501
                        logMetacat.debug("MetaCatServlet.handleUploadAction - ForceReplicationHandler created: " + frh.toString());
2502

    
2503
                        // set content type and other response header fields
2504
                        // first
2505
                        output += "<?xml version=\"1.0\"?>";
2506
                        output += "<success>";
2507
                        output += "<docid>" + docid + "</docid>";
2508
                        output += "<size>" + size + "</size>";
2509
                        output += "</success>";
2510
                    }
2511

    
2512
                } catch (Exception e) {
2513

    
2514
                    output += "<?xml version=\"1.0\"?>";
2515
                    output += "<error>";
2516
                    output += e.getMessage();
2517
                    output += "</error>";
2518
                }
2519
            } else {
2520
                // the field did not contain a file
2521
                output += "<?xml version=\"1.0\"?>";
2522
                output += "<error>";
2523
                output += "The uploaded data did not contain a valid file.";
2524
                output += "</error>";
2525
            }
2526
        } else {
2527
            // Error bcse docid missing or file missing
2528
            output += "<?xml version=\"1.0\"?>";
2529
            output += "<error>";
2530
            output += "The uploaded data did not contain a valid docid "
2531
                + "or valid file.";
2532
            output += "</error>";
2533
        }
2534

    
2535
        if (qformat == null || qformat.equals("xml")) {
2536
            response.setContentType("text/xml");
2537
            out.println(output);
2538
        } else {
2539
            try {
2540
                DBTransform trans = new DBTransform();
2541
                response.setContentType("text/html");
2542
                trans.transformXMLDocument(output,
2543
                        "message", "-//W3C//HTML//EN", qformat,
2544
                        out, null, null);
2545
            } catch (Exception e) {
2546

    
2547
                logMetacat.error("MetaCatServlet.handleUploadAction - General error: "
2548
                        + e.getMessage());
2549
                e.printStackTrace(System.out);
2550
            }
2551
        }
2552
    }
2553
    
2554
    /*
2555
     * A method to handle set access action
2556
     */
2557
    protected void handleSetAccessAction(PrintWriter out, Hashtable<String, String[]> params,
2558
            String username, HttpServletRequest request, HttpServletResponse response) {
2559
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2560

    
2561
        String permission = null;
2562
        String permType = null;
2563
        String permOrder = null;
2564
        Vector<String> errorList = new Vector<String>();
2565
        String error = null;
2566
        Vector<String> successList = new Vector<String>();
2567
        String success = null;
2568
        boolean isEmlPkgMember = false;
2569
        
2570
        String[] docList = params.get("docid");
2571
        String[] principalList = params.get("principal");
2572
        String[] permissionList = params.get("permission");
2573
        String[] permTypeList = params.get("permType");
2574
        String[] permOrderList = params.get("permOrder");
2575
        String[] qformatList = params.get("qformat");
2576
        String[] accessBlock = params.get("accessBlock");
2577
        
2578
        if(accessBlock != null) {
2579
            if (docList == null) {
2580
                errorList.addElement("MetaCatServlet.handleSetAccessAction - Doc id missing.  Please check your parameter list, it should look like: "
2581
                    + "?action=setaccess&docid=<doc_id>&accessBlock=<access_section>");
2582
                outputResponse(successList, errorList, out);
2583
                return;
2584
            }
2585
            
2586
            try {
2587
                AccessControlForSingleFile accessControl = 
2588
                    new AccessControlForSingleFile(docList[0]);
2589
                accessControl.insertPermissions(accessBlock[0]);
2590
                successList.addElement("MetaCatServlet.handleSetAccessAction - successfully replaced access block for doc id: " + docList[0]);
2591
            } catch(AccessControlException ace) {
2592
                errorList.addElement("MetaCatServlet.handleSetAccessAction - access control error when setting " + 
2593
                    "access block: " + ace.getMessage());
2594
            } 
2595
            outputResponse(successList, errorList, out);
2596
            return;
2597
        }
2598
        
2599
        // Make sure the parameter is not null
2600
        if (docList == null || principalList == null || permTypeList == null
2601
                || permissionList == null) {
2602
            error = "MetaCatServlet.handleSetAccessAction - Please check your parameter list, it should look like: "
2603
                    + "?action=setaccess&docid=pipeline.1.1&principal=public"
2604
                    + "&permission=read&permType=allow&permOrder=allowFirst";
2605
            errorList.addElement(error);
2606
            outputResponse(successList, errorList, out);
2607
            return;
2608
        }
2609
        
2610
        // Only select first element for permission, type and order
2611
        permission = permissionList[0];
2612
        permType = permTypeList[0];
2613
        if (permOrderList != null) {
2614
            permOrder = permOrderList[0];
2615
        }
2616
        
2617
        // Get package doctype set
2618
        Vector<String> packageSet = null;
2619
        try {
2620
            packageSet = 
2621
                MetacatUtil.getOptionList(PropertyService.getProperty("xml.packagedoctypeset"));
2622
        } catch (PropertyNotFoundException pnfe) {
2623
            logMetacat.error("MetaCatServlet.handleSetAccessAction - Could not find package doctype set.  Setting to null: " 
2624
                    + pnfe.getMessage());
2625
        }
2626
        //debug
2627
        if (packageSet != null) {
2628
            for (int i = 0; i < packageSet.size(); i++) {
2629
                logMetacat.debug("MetaCatServlet.handleSetAccessAction - doctype in package set: "
2630
                        + packageSet.elementAt(i));
2631
            }
2632
        }
2633
        
2634
        // handle every accessionNumber
2635
        for (int i = 0; i < docList.length; i++) {
2636
            String docid = docList[i];
2637
            if (docid.startsWith("urn:")) {
2638
                try {
2639
                    String actualDocId = LSIDUtil.getDocId(docid, false);
2640
                    docid = actualDocId;
2641
                } catch (ParseLSIDException ple) {
2642
                    logMetacat.error("MetaCatServlet.handleSetAccessAction - " +
2643
                            "could not parse lsid: " + docid + " : " + ple.getMessage()); 
2644
                    ple.printStackTrace(System.out);
2645
                }
2646
            }
2647
            
2648
            String accessionNumber = docid;
2649
            String owner = null;
2650
            String publicId = null;
2651
            // Get document owner and public id
2652
            try {
2653
                owner = getFieldValueForDoc(accessionNumber, "user_owner");
2654
                publicId = getFieldValueForDoc(accessionNumber, "doctype");
2655
            } catch (Exception e) {
2656
                logMetacat.error("MetaCatServlet.handleSetAccessAction - Error in handleSetAccessAction: "
2657
                        + e.getMessage());
2658
                e.printStackTrace(System.out);
2659
                error = "Error in set access control for document - " + accessionNumber + e.getMessage();
2660
                errorList.addElement(error);
2661
                continue;
2662
            }
2663
            //check if user is the owner. Only owner can do owner
2664
            if (username == null || owner == null || !username.equals(owner)) {
2665
                error = "User - " + username + " does not have permission to set "
2666
                        + "access control for docid - " + accessionNumber;
2667
                errorList.addElement(error);
2668
                continue;
2669
            }
2670
            
2671
            //*** Find out if the document is a Member of an EML package.
2672
            //*** (for efficiency, only check if it isn't already true
2673
            //*** for the case of multiple files).
2674
            if (isEmlPkgMember == false)
2675
                isEmlPkgMember = (DBUtil.findDataSetDocIdForGivenDocument(accessionNumber) != null);
2676
            
2677
            // If docid publicid is BIN data file or other beta4, 6 package document
2678
            // we could not do set access control. Because we don't want inconsistent
2679
            // to its access docuemnt
2680
            if (publicId != null && packageSet != null
2681
                    && packageSet.contains(publicId) && isEmlPkgMember) {
2682
                error = "Could not set access control to document " + accessionNumber
2683
                        + "because it is in a pakcage and it has a access file for it";
2684
                errorList.addElement(error);
2685
                continue;
2686
            }
2687
            
2688
            // for every principle
2689
            for (int j = 0; j < principalList.length; j++) {
2690
                String principal = principalList[j];
2691
                try {
2692
                    //insert permission
2693
                    AccessControlForSingleFile accessControl = 
2694
                        new AccessControlForSingleFile(accessionNumber);
2695
                    accessControl.insertPermissions(principal, Long.valueOf(permission), permType, permOrder);
2696
                } catch (Exception ee) {
2697
                    logMetacat.error("MetaCatServlet.handleSetAccessAction - Error inserting permission: "
2698
                            + ee.getMessage());
2699
                    ee.printStackTrace(System.out);
2700
                    error = "Failed to set access control for document "
2701
                            + accessionNumber + " because " + ee.getMessage();
2702
                    errorList.addElement(error);
2703
                    continue;
2704
                }
2705
            }
2706
            
2707
            //force replication when this action is called
2708
            boolean isXml = true;
2709
            if (publicId.equalsIgnoreCase("BIN")) {
2710
                isXml = false;
2711
            }
2712
            ForceReplicationHandler frh = 
2713
                new ForceReplicationHandler(accessionNumber, isXml, null);
2714
            logMetacat.debug("MetaCatServlet.handleSetAccessAction - ForceReplicationHandler created: " + frh.toString());
2715
            
2716
        }
2717
        successList.addElement("MetaCatServlet.handleSetAccessAction - successfully added individual access for doc id: " + docList[0]);
2718
        
2719
        if (params.get("forwardto")  != null) {
2720
            try {
2721
                RequestUtil.forwardRequest(request, response, params);
2722
            } catch (MetacatUtilException mue) {
2723
                logMetacat.error("metaCatServlet.handleSetAccessAction - could not forward " +
2724
                        "request. Sending output to response writer");
2725
                mue.printStackTrace(System.out);
2726
                outputResponse(successList, errorList, out);
2727
            }               
2728
        } else {
2729
            outputResponse(successList, errorList, out);
2730
        }
2731
    }
2732
    
2733
    /*
2734
     * A method try to determin a docid's public id, if couldn't find null will
2735
     * be returned.
2736
     */
2737
    private String getFieldValueForDoc(String accessionNumber, String fieldName)
2738
    throws Exception {
2739
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2740
        if (accessionNumber == null || accessionNumber.equals("")
2741
        || fieldName == null || fieldName.equals("")) { throw new Exception(
2742
                "Docid or field name was not specified"); }
2743
        
2744
        PreparedStatement pstmt = null;
2745
        ResultSet rs = null;
2746
        String fieldValue = null;
2747
        String docId = null;
2748
        DBConnection conn = null;
2749
        int serialNumber = -1;
2750
        
2751
        // get rid of revision if access number has
2752
        docId = DocumentUtil.getDocIdFromString(accessionNumber);
2753
        try {
2754
            //check out DBConnection
2755
            conn = DBConnectionPool
2756
                    .getDBConnection("MetaCatServlet.getPublicIdForDoc");
2757
            serialNumber = conn.getCheckOutSerialNumber();
2758
            pstmt = conn.prepareStatement("SELECT " + fieldName
2759
                    + " FROM xml_documents " + "WHERE docid = ? ");
2760
            
2761
            pstmt.setString(1, docId);
2762
            pstmt.execute();
2763
            rs = pstmt.getResultSet();
2764
            boolean hasRow = rs.next();
2765
        //    int perm = 0;
2766
            if (hasRow) {
2767
                fieldValue = rs.getString(1);
2768
            } else {
2769
                throw new Exception("Could not find document: "
2770
                        + accessionNumber);
2771
            }
2772
        } catch (Exception e) {
2773
            logMetacat.error("MetaCatServlet.getFieldValueForDoc - General error: "
2774
                    + e.getMessage());
2775
            throw e;
2776
        } finally {
2777
            try {
2778
                rs.close();
2779
                pstmt.close();
2780
                
2781
            } finally {
2782
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2783
            }
2784
        }
2785
        return fieldValue;
2786
    }
2787
    
2788
    /*
2789
     * Get the list of documents from the database and return the list in an
2790
     * Vector of identifiers.
2791
     *
2792
     * @ returns the array of identifiers
2793
     */
2794
    private Vector<String> getDocumentList() throws SQLException {
2795
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2796
        Vector<String> docList = new Vector<String>();
2797
        PreparedStatement pstmt = null;
2798
        ResultSet rs = null;
2799
        DBConnection conn = null;
2800
        int serialNumber = -1;
2801
        
2802
        try {
2803
            //check out DBConnection
2804
            conn = DBConnectionPool
2805
                    .getDBConnection("MetaCatServlet.getDocumentList");
2806
            serialNumber = conn.getCheckOutSerialNumber();
2807
            pstmt = conn.prepareStatement("SELECT docid, rev"
2808
                    + " FROM xml_documents ");
2809
            pstmt.execute();
2810
            rs = pstmt.getResultSet();
2811
            while (rs.next()) {
2812
                String docid = rs.getString(1);
2813
                String rev = rs.getString(2);
2814
                docList.add(docid + "." + rev);
2815
            }
2816
        } catch (SQLException e) {
2817
            logMetacat.error("MetaCatServlet.getDocumentList - General exception: "
2818
                    + e.getMessage());
2819
            throw e;
2820
        } finally {
2821
            try {
2822
                rs.close();
2823
                pstmt.close();
2824
                
2825
            } catch (SQLException se) {
2826
                logMetacat.error("MetaCatServlet.getDocumentList - General exception: "
2827
                        + se.getMessage());
2828
                throw se;
2829
            } finally {
2830
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2831
            }
2832
        }
2833
        return docList;
2834
    }
2835
    
2836
    /*
2837
     * A method to output setAccess action result
2838
     */
2839
    private void outputResponse(Vector<String> successList, Vector<String> errorList,
2840
            PrintWriter out) {
2841
        boolean error = false;
2842
        boolean success = false;
2843
        // Output prolog
2844
        out.println(PROLOG);
2845
        // output success message
2846
        if (successList != null) {
2847
            for (int i = 0; i < successList.size(); i++) {
2848
                out.println(SUCCESS);
2849
                out.println(successList.elementAt(i));
2850
                out.println(SUCCESSCLOSE);
2851
                success = true;
2852
            }
2853
        }
2854
        // output error message
2855
        if (errorList != null) {
2856
            for (int i = 0; i < errorList.size(); i++) {
2857
                out.println(ERROR);
2858
                out.println(errorList.elementAt(i));
2859
                out.println(ERRORCLOSE);
2860
                error = true;
2861
            }
2862
        }
2863
        
2864
        // if no error and no success info, send a error that nothing happened
2865
        if (!error && !success) {
2866
            out.println(ERROR);
2867
            out.println("Nothing happend for setaccess action");
2868
            out.println(ERRORCLOSE);
2869
        }
2870
    }
2871
    
2872
    /*
2873
     * If the given docid only have one seperter, we need
2874
     * append rev for it. The rev come from xml_documents
2875
     */
2876
    private static String appendRev(String docid) throws PropertyNotFoundException, SQLException, McdbDocNotFoundException {
2877
//        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2878
        String newAccNum = null;
2879
        String separator = PropertyService.getProperty("document.accNumSeparator");
2880
        int firstIndex = docid.indexOf(separator);
2881
        int lastIndex = docid.lastIndexOf(separator);
2882
        if (firstIndex == lastIndex) {
2883
            
2884
            //only one seperater
2885
            int rev = DBUtil.getLatestRevisionInDocumentTable(docid);
2886
            if (rev == -1) {
2887
                throw new McdbDocNotFoundException("the requested docid '"
2888
                        + docid+ "' does not exist");
2889
            } else {
2890
                newAccNum = docid+ separator+ rev;
2891
            }
2892
        } else {
2893
            // in other suituation we don't change the docid
2894
            newAccNum = docid;
2895
        }
2896
        //logMetacat.debug("The docid will be read is "+newAccNum);
2897
        return newAccNum;
2898
    }
2899
    
2900
    /**
2901
     * Schedule the sitemap generator to run periodically and update all
2902
     * of the sitemap files for search indexing engines.
2903
     *
2904
     * @param request a servlet request, from which we determine the context
2905
     */
2906
    protected void scheduleSitemapGeneration(HttpServletRequest request) {
2907
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2908
        if (!_sitemapScheduled) {
2909
            String directoryName = null;
2910
            String skin = null;
2911
            long sitemapInterval = 0;
2912
            
2913
            try {
2914
                directoryName = SystemUtil.getContextDir() + FileUtil.getFS() + "sitemaps";
2915
                skin = PropertyService.getProperty("application.default-style");
2916
                sitemapInterval = 
2917
                    Integer.parseInt(PropertyService.getProperty("sitemap.interval"));
2918
            } catch (PropertyNotFoundException pnfe) {
2919
                logMetacat.error("MetaCatServlet.scheduleSitemapGeneration - Could not run site map generation because property " 
2920
                        + "could not be found: " + pnfe.getMessage());
2921
            }
2922
            
2923
            File directory = new File(directoryName);
2924
            directory.mkdirs();
2925
            String urlRoot = request.getRequestURL().toString();
2926
            Sitemap smap = new Sitemap(directory, urlRoot, skin);
2927
            long firstDelay = 60*1000;   // 60 seconds delay
2928
            timer.schedule(smap, firstDelay, sitemapInterval);
2929
            _sitemapScheduled = true;
2930
        }
2931
    }
2932

    
2933
    /**
2934
     * @param sitemapScheduled toggle the _sitemapScheduled flag
2935
     */
2936
    public void set_sitemapScheduled(boolean sitemapScheduled) {
2937
        _sitemapScheduled = sitemapScheduled;
2938
    }
2939

    
2940
}
(43-43/62)