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

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

    
64
import au.com.bytecode.opencsv.CSVWriter;
65

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

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

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

    
108
    private static boolean _sitemapScheduled = false;
109

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

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

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

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

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

    
1033
    /**
1034
     * Create a filename to be used for naming a downloaded document
1035
     * @param docid the identifier of the document to be named
1036
     * @param params the parameters of the request
1037
     * @param doc the DocumentImpl of the document to be named
1038
     * @return String containing a name for the download
1039
     */
1040
    private String generateOutputName(String docid,
1041
            Hashtable<String, String[]> params, DocumentImpl doc) {
1042
        String outputname = null;
1043
        // check for the existence of a metadatadocid parameter,
1044
        // if this is sent, then send a filename which contains both
1045
        // the metadata docid and the data docid, so the link with
1046
        // metadata is explicitly encoded in the filename.
1047
        String metadatadocid = null;
1048
        Vector<String> nameparts = new Vector<String>();
1049

    
1050
        if(params.containsKey("metadatadocid")) {
1051
            metadatadocid = params.get("metadatadocid")[0];
1052
        }
1053
        if (metadatadocid != null && !metadatadocid.equals("")) {
1054
            nameparts.add(metadatadocid);
1055
        }
1056
        // we'll always have the docid, include it in the name
1057
        String doctype = doc.getDoctype();
1058
        // TODO: fix this to lookup the associated FGDC metadata document,
1059
        // and grab the doctype tag for it.  These should be set to something 
1060
        // consistent, not 'metadata' as it stands...
1061
        //if (!doctype.equals("metadata")) {
1062
        //    nameparts.add(docid);
1063
        //} 
1064
        nameparts.add(docid);
1065
        // Set the name of the data file to the entity name plus docid,
1066
        // or if that is unavailable, use the docid alone
1067
        String docname = doc.getDocname();
1068
        if (docname != null && !docname.equals("")) {
1069
            nameparts.add(docname); 
1070
        }
1071
        // combine the name elements with a dash, using a 'join' equivalent
1072
        String delimiter = "-";
1073
        Iterator<String> iter = nameparts.iterator();
1074
        StringBuffer buffer = new StringBuffer(iter.next());
1075
        while (iter.hasNext()) buffer.append(delimiter).append(iter.next());
1076
        outputname = buffer.toString();
1077
        return outputname;
1078
    }
1079
    
1080
    /**
1081
     * read data from URLConnection
1082
     */
1083
    private void readFromURLConnection(HttpServletResponse response,
1084
            String docid) throws IOException, MalformedURLException {
1085
        ServletOutputStream out = response.getOutputStream();
1086
        String contentType = servletContext.getMimeType(docid); //MIME type
1087
        if (contentType == null) {
1088
            if (docid.endsWith(".xml")) {
1089
                contentType = "text/xml";
1090
            } else if (docid.endsWith(".css")) {
1091
                contentType = "text/css";
1092
            } else if (docid.endsWith(".dtd")) {
1093
                contentType = "text/plain";
1094
            } else if (docid.endsWith(".xsd")) {
1095
                contentType = "text/xml";
1096
            } else if (docid.endsWith("/")) {
1097
                contentType = "text/html";
1098
            } else {
1099
                File f = new File(docid);
1100
                if (f.isDirectory()) {
1101
                    contentType = "text/html";
1102
                } else {
1103
                    contentType = "application/octet-stream";
1104
                }
1105
            }
1106
        }
1107
        response.setContentType(contentType);
1108
        // if we decide to use "application/octet-stream" for all data returns
1109
        // response.setContentType("application/octet-stream");
1110
        
1111
        // this is http url
1112
        URL url = new URL(docid);
1113
        BufferedInputStream bis = null;
1114
        try {
1115
            bis = new BufferedInputStream(url.openStream());
1116
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1117
            int b = bis.read(buf);
1118
            while (b != -1) {
1119
                out.write(buf, 0, b);
1120
                b = bis.read(buf);
1121
            }
1122
        } finally {
1123
            if (bis != null) bis.close();
1124
        }
1125
        
1126
    }
1127
    
1128
    /**
1129
     * read file/doc and write to ZipOutputStream
1130
     *
1131
     * @param docid
1132
     * @param zout
1133
     * @param user
1134
     * @param groups
1135
     * @throws ClassNotFoundException
1136
     * @throws IOException
1137
     * @throws SQLException
1138
     * @throws McdbException
1139
     * @throws Exception
1140
     */
1141
    private void addDocToZip(HttpServletRequest request, String docid, String providedFileName,
1142
            ZipOutputStream zout, String user, String[] groups) throws
1143
            ClassNotFoundException, IOException, SQLException, McdbException,
1144
            Exception {
1145
        byte[] bytestring = null;
1146
        ZipEntry zentry = null;
1147
        
1148
        try {
1149
            URL url = new URL(docid);
1150
            
1151
            // this http url; read from URLConnection; add to zip
1152
            //use provided file name if we have one
1153
            if (providedFileName != null && providedFileName.length() > 1) {
1154
                zentry = new ZipEntry(providedFileName);
1155
            }
1156
            else {
1157
                zentry = new ZipEntry(docid);
1158
            }
1159
            zout.putNextEntry(zentry);
1160
            BufferedInputStream bis = null;
1161
            try {
1162
                bis = new BufferedInputStream(url.openStream());
1163
                byte[] buf = new byte[4 * 1024]; // 4K buffer
1164
                int b = bis.read(buf);
1165
                while (b != -1) {
1166
                    zout.write(buf, 0, b);
1167
                    b = bis.read(buf);
1168
                }
1169
            } finally {
1170
                if (bis != null) bis.close();
1171
            }
1172
            zout.closeEntry();
1173
            
1174
        } catch (MalformedURLException mue) {
1175
            
1176
            // this is metacat doc (data file or metadata doc)
1177
            try {
1178
                DocumentImpl doc = new DocumentImpl(docid);
1179
                
1180
                //check the permission for read
1181
                if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1182
                    Exception e = new Exception("User " + user
1183
                            + " does not have "
1184
                            + "permission to read the document with the docid "
1185
                            + docid);
1186
                    throw e;
1187
                }
1188
                
1189
                if (doc.getRootNodeID() == 0) {
1190
                    // this is data file; add file to zip
1191
                    String filepath = PropertyService.getProperty("application.datafilepath");
1192
                    if (!filepath.endsWith("/")) {
1193
                        filepath += "/";
1194
                    }
1195
                    String filename = filepath + docid;
1196
                    FileInputStream fin = null;
1197
                    fin = new FileInputStream(filename);
1198
                    try {
1199
                        //use provided file name if we have one
1200
                        if (providedFileName != null && providedFileName.length() > 1) {
1201
                            zentry = new ZipEntry(providedFileName);
1202
                        }
1203
                        else {
1204
                            zentry = new ZipEntry(docid);
1205
                        }
1206
                        zout.putNextEntry(zentry);
1207
                        byte[] buf = new byte[4 * 1024]; // 4K buffer
1208
                        int b = fin.read(buf);
1209
                        while (b != -1) {
1210
                            zout.write(buf, 0, b);
1211
                            b = fin.read(buf);
1212
                        }
1213
                    } finally {
1214
                        if (fin != null) fin.close();
1215
                    }
1216
                    zout.closeEntry();
1217
                    
1218
                } else {
1219
                    // this is metadata doc; add doc to zip
1220
                    bytestring = doc.toString().getBytes();
1221
                    //use provided file name if given
1222
                    if (providedFileName != null && providedFileName.length() > 1) {
1223
                        zentry = new ZipEntry(providedFileName);
1224
                    }
1225
                    else {
1226
                        zentry = new ZipEntry(docid + ".xml");
1227
                    }
1228
                    zentry.setSize(bytestring.length);
1229
                    zout.putNextEntry(zentry);
1230
                    zout.write(bytestring, 0, bytestring.length);
1231
                    zout.closeEntry();
1232
                }
1233
                EventLog.getInstance().log(request.getRemoteAddr(), user,
1234
                        docid, "read");
1235
            } catch (Exception except) {
1236
                throw except;
1237
            }
1238
        }
1239
    }
1240
    
1241
    /**
1242
     * If metacat couldn't find a data file or document locally, it will read
1243
     * this docid from its home server. This is for the replication feature
1244
     */
1245
    private void readFromRemoteMetaCat(HttpServletResponse response,
1246
            String docid, String rev, String user, String password,
1247
            ServletOutputStream out, boolean zip, ZipOutputStream zout)
1248
            throws Exception {
1249
        // Create a object of RemoteDocument, "" is for zipEntryPath
1250
        RemoteDocument remoteDoc = new RemoteDocument(docid, rev, user,
1251
                password, "");
1252
        String docType = remoteDoc.getDocType();
1253
        // Only read data file
1254
        if (docType.equals("BIN")) {
1255
            // If it is zip format
1256
            if (zip) {
1257
                remoteDoc.readDocumentFromRemoteServerByZip(zout);
1258
            } else {
1259
                if (out == null) {
1260
                    out = response.getOutputStream();
1261
                }
1262
                response.setContentType("application/octet-stream");
1263
                remoteDoc.readDocumentFromRemoteServer(out);
1264
            }
1265
        } else {
1266
            throw new Exception("Docid: " + docid + "." + rev
1267
                    + " couldn't find");
1268
        }
1269
    }
1270
    
1271
    /**
1272
     * Handle the database putdocument request and write an XML document to the
1273
     * database connection
1274
     */
1275
    public void handleInsertOrUpdateAction(HttpServletRequest request,
1276
            HttpServletResponse response, PrintWriter out, Hashtable<String, String[]> params,
1277
            String user, String[] groups) {
1278
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1279
        DBConnection dbConn = null;
1280
        int serialNumber = -1;
1281
        String output = "";
1282
        String qformat = null;
1283
        if(params.containsKey("qformat"))
1284
        {
1285
          qformat = params.get("qformat")[0];
1286
        }
1287
        
1288
        if(params.get("docid") == null){
1289
            out.println("<?xml version=\"1.0\"?>");
1290
            out.println("<error>");
1291
            out.println("Docid not specified");
1292
            out.println("</error>");
1293
            logMetacat.error("MetaCatServlet.handleInsertOrUpdateAction - Docid not specified");
1294
            return;
1295
        }
1296
        
1297
        try {
1298
            if (!AuthUtil.canInsertOrUpdate(user, groups)) {
1299
                out.println("<?xml version=\"1.0\"?>");
1300
                out.println("<error>");
1301
                out.println("User '" + user + "' not allowed to insert and update");
1302
                out.println("</error>");
1303
                logMetacat.error("MetaCatServlet.handleInsertOrUpdateAction - User '" + user + "' not allowed to insert and update");
1304
                return;
1305
            }
1306
        } catch (MetacatUtilException ue) {
1307
            logMetacat.error("MetaCatServlet.handleInsertOrUpdateAction - Could not determine if user could insert or update: "
1308
                    + ue.getMessage());
1309
        }
1310
        
1311
        try {
1312
            // Get the document indicated
1313
            logMetacat.debug("MetaCatServlet.handleInsertOrUpdateAction - params: " + params.toString());
1314
            
1315
            String[] doctext = params.get("doctext");
1316
            String pub = null;
1317
            if (params.containsKey("public")) {
1318
                pub = params.get("public")[0];
1319
            }
1320
            
1321
            StringReader dtd = null;
1322
            if (params.containsKey("dtdtext")) {
1323
                String[] dtdtext = params.get("dtdtext");
1324
                try {
1325
                    if (!dtdtext[0].equals("")) {
1326
                        dtd = new StringReader(dtdtext[0]);
1327
                    }
1328
                } catch (NullPointerException npe) {
1329
                }
1330
            }
1331
            
1332
            if(doctext == null){
1333
                out.println("<?xml version=\"1.0\"?>");
1334
                out.println("<error>");
1335
                out.println("Document text not submitted");
1336
                out.println("</error>");
1337
                return;
1338
            }
1339
            
1340
            logMetacat.debug("MetaCatServlet.handleInsertOrUpdateAction - the xml document in metacat servlet (before parsing):\n" + doctext[0]);
1341
            StringReader xmlReader = new StringReader(doctext[0]);
1342
            boolean validate = false;
1343
            DocumentImplWrapper documentWrapper = null;
1344
            try {
1345
                // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ...
1346
                // >
1347
                // in order to decide whether to use validation parser
1348
                validate = needDTDValidation(xmlReader);
1349
                if (validate) {
1350
                    // set a dtd base validation parser
1351
                    String rule = DocumentImpl.DTD;
1352
                    documentWrapper = new DocumentImplWrapper(rule, validate);
1353
                } else {
1354
                    
1355
                    String namespace = XMLSchemaService.findDocumentNamespace(xmlReader);
1356
                    
1357
                    if (namespace != null) {
1358
                        if (namespace.compareTo(DocumentImpl.EML2_0_0NAMESPACE) == 0
1359
                                || namespace.compareTo(
1360
                                DocumentImpl.EML2_0_1NAMESPACE) == 0) {
1361
                            // set eml2 base     validation parser
1362
                            String rule = DocumentImpl.EML200;
1363
                            // using emlparser to check id validation
1364
                            @SuppressWarnings("unused")
1365
                            EMLParser parser = new EMLParser(doctext[0]);
1366
                            documentWrapper = new DocumentImplWrapper(rule, true);
1367
                        } else if (namespace.compareTo(
1368
                                DocumentImpl.EML2_1_0NAMESPACE) == 0) {
1369
                            // set eml2 base validation parser
1370
                            String rule = DocumentImpl.EML210;
1371
                            // using emlparser to check id validation
1372
                            @SuppressWarnings("unused")
1373
                            EMLParser parser = new EMLParser(doctext[0]);
1374
                            documentWrapper = new DocumentImplWrapper(rule, true);
1375
                        } else {
1376
                            // set schema base validation parser
1377
                            String rule = DocumentImpl.SCHEMA;
1378
                            documentWrapper = new DocumentImplWrapper(rule, true);
1379
                        }
1380
                    } else {
1381
                        documentWrapper = new DocumentImplWrapper("", false);
1382
                    }
1383
                }
1384
                
1385
                String[] action = params.get("action");
1386
                String[] docid = params.get("docid");
1387
                String newdocid = null;
1388
                
1389
                String doAction = null;
1390
                if (action[0].equals("insert") || action[0].equals("insertmultipart")) {
1391
                    doAction = "INSERT";
1392
                } else if (action[0].equals("update")) {
1393
                    doAction = "UPDATE";
1394
                }
1395
                
1396
                try {
1397
                    // get a connection from the pool
1398
                    dbConn = DBConnectionPool
1399
                            .getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1400
                    serialNumber = dbConn.getCheckOutSerialNumber();
1401
                    
1402
                    // write the document to the database and disk
1403
                    String accNumber = docid[0];
1404
                    logMetacat.debug("MetaCatServlet.handleInsertOrUpdateAction - " + doAction + " "
1405
                            + accNumber + "...");
1406
                    if (accNumber == null || accNumber.equals("")) {
1407
                        logMetacat.warn("MetaCatServlet.handleInsertOrUpdateAction - writing with null acnumber");
1408
                        newdocid = documentWrapper.write(dbConn, doctext[0], pub, dtd,
1409
                                doAction, null, user, groups);
1410
                        EventLog.getInstance().log(request.getRemoteAddr(),
1411
                                user, "", action[0]);
1412
                        } else {
1413
                            newdocid = documentWrapper.write(dbConn, doctext[0], pub, dtd,
1414
                                    doAction, accNumber, user, groups);
1415
                            
1416
                            EventLog.getInstance().log(request.getRemoteAddr(),
1417
                                    user, accNumber, action[0]);
1418
                        }
1419
                } finally {
1420
                    // Return db connection
1421
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1422
                }
1423
                
1424
                // set content type and other response header fields first
1425
                //response.setContentType("text/xml");
1426
                output += "<?xml version=\"1.0\"?>";
1427
                output += "<success>";
1428
                output += "<docid>" + newdocid + "</docid>";
1429
                output += "</success>";
1430
                
1431
            } catch (NullPointerException npe) {
1432
                //response.setContentType("text/xml");
1433
                output += "<?xml version=\"1.0\"?>";
1434
                output += "<error>";
1435
                output += npe.getMessage();
1436
                output += "</error>";
1437
                logMetacat.warn("MetaCatServlet.handleInsertOrUpdateAction - Null pointer error when writing eml document to the database: " + npe.getMessage());
1438
                npe.printStackTrace();
1439
            }
1440
        } catch (Exception e) {
1441
            //response.setContentType("text/xml");
1442
            output += "<?xml version=\"1.0\"?>";
1443
            output += "<error>";
1444
            output += e.getMessage();
1445
            output += "</error>";
1446
            logMetacat.warn("MetaCatServlet.handleInsertOrUpdateAction - General error when writing eml document to the database: " + e.getMessage());
1447
            e.printStackTrace();
1448
        }
1449
        
1450
        if (qformat == null || qformat.equals("xml")) {
1451
            response.setContentType("text/xml");
1452
            out.println(output);
1453
        } else {
1454
            try {
1455
                DBTransform trans = new DBTransform();
1456
                response.setContentType("text/html");
1457
                trans.transformXMLDocument(output,
1458
                        "message", "-//W3C//HTML//EN", qformat,
1459
                        out, null, null);
1460
            } catch (Exception e) {
1461
                
1462
                logMetacat.error("MetaCatServlet.handleInsertOrUpdateAction - General error: "
1463
                        + e.getMessage());
1464
            }
1465
        }
1466
    }
1467
    
1468
    /**
1469
     * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > in
1470
     * order to decide whether to use validation parser
1471
     */
1472
    private static boolean needDTDValidation(StringReader xmlreader)
1473
    throws IOException {
1474
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1475
        StringBuffer cbuff = new StringBuffer();
1476
        java.util.Stack<String> st = new java.util.Stack<String>();
1477
        boolean validate = false;
1478
        boolean commented = false;
1479
        int c;
1480
        int inx;
1481
        
1482
        // read from the stream until find the keywords
1483
        while ((st.empty() || st.size() < 4) && ((c = xmlreader.read()) != -1)) {
1484
            cbuff.append((char) c);
1485
            
1486
            if ((inx = cbuff.toString().indexOf("<!--")) != -1) {
1487
                commented = true;
1488
            }
1489
            
1490
            // "<!DOCTYPE" keyword is found; put it in the stack
1491
            if ((inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1) {
1492
                cbuff = new StringBuffer();
1493
                st.push("<!DOCTYPE");
1494
            }
1495
            // "PUBLIC" keyword is found; put it in the stack
1496
            if ((inx = cbuff.toString().indexOf("PUBLIC")) != -1) {
1497
                cbuff = new StringBuffer();
1498
                st.push("PUBLIC");
1499
            }
1500
            // "SYSTEM" keyword is found; put it in the stack
1501
            if ((inx = cbuff.toString().indexOf("SYSTEM")) != -1) {
1502
                cbuff = new StringBuffer();
1503
                st.push("SYSTEM");
1504
            }
1505
            // ">" character is found; put it in the stack
1506
            // ">" is found twice: fisrt from <?xml ...?>
1507
            // and second from <!DOCTYPE ... >
1508
            if ((inx = cbuff.toString().indexOf(">")) != -1) {
1509
                cbuff = new StringBuffer();
1510
                st.push(">");
1511
            }
1512
        }
1513
        
1514
        // close the stream
1515
        xmlreader.reset();
1516
        
1517
        // check the stack whether it contains the keywords:
1518
        // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1519
        if (st.size() == 4) {
1520
            if ((st.pop()).equals(">")
1521
            && ((st.peek()).equals("PUBLIC") | (st.pop()).equals("SYSTEM"))
1522
                    && (st.pop()).equals("<!DOCTYPE")) {
1523
                validate = true && !commented;
1524
            }
1525
        }
1526
        
1527
        logMetacat.info("MetaCatServlet.needDTDValidation - Validation for dtd is " + validate);
1528
        return validate;
1529
    }
1530
    
1531
    // END OF INSERT/UPDATE SECTION
1532
    
1533
    /**
1534
     * Handle the database delete request and delete an XML document from the
1535
     * database connection
1536
     */
1537
    public void handleDeleteAction(PrintWriter out, Hashtable<String, String[]> params,
1538
            HttpServletRequest request, HttpServletResponse response,
1539
            String user, String[] groups) {
1540
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1541
        String[] docid = params.get("docid");
1542
        
1543
        if(docid == null){
1544
            response.setContentType("text/xml");
1545
            out.println("<?xml version=\"1.0\"?>");
1546
            out.println("<error>");
1547
            out.println("Docid not specified.");
1548
            out.println("</error>");
1549
            logMetacat.error("MetaCatServlet.handleDeleteAction - Docid not specified for the document to be deleted.");
1550
        } else {
1551
            
1552
            // delete the document from the database
1553
            try {
1554
                
1555
                try {
1556
                    // null means notify server is null
1557
                    DocumentImpl.delete(docid[0], user, groups, null);
1558
                    EventLog.getInstance().log(request.getRemoteAddr(),
1559
                            user, docid[0], "delete");
1560
                    response.setContentType("text/xml");
1561
                    out.println("<?xml version=\"1.0\"?>");
1562
                    out.println("<success>");
1563
                    out.println("Document deleted.");
1564
                    out.println("</success>");
1565
                    logMetacat.info("MetaCatServlet.handleDeleteAction - Document deleted.");
1566
                    
1567
                    // Delete from spatial cache if runningSpatialOption
1568
                    if ( PropertyService.getProperty("spatial.runSpatialOption").equals("true") ) {
1569
                        SpatialHarvester sh = new SpatialHarvester();
1570
                        sh.addToDeleteQue( DocumentUtil.getSmartDocId( docid[0] ) );
1571
                        sh.destroy();
1572
                    }
1573
                    
1574
                } catch (AccessionNumberException ane) {
1575
                    response.setContentType("text/xml");
1576
                    out.println("<?xml version=\"1.0\"?>");
1577
                    out.println("<error>");
1578
                    //out.println("Error deleting document!!!");
1579
                    out.println(ane.getMessage());
1580
                    out.println("</error>");
1581
                    logMetacat.error("MetaCatServlet.handleDeleteAction - Document could not be deleted: "
1582
                            + ane.getMessage());
1583
                }
1584
            } catch (Exception e) {
1585
                response.setContentType("text/xml");
1586
                out.println("<?xml version=\"1.0\"?>");
1587
                out.println("<error>");
1588
                out.println(e.getMessage());
1589
                out.println("</error>");
1590
                logMetacat.error("MetaCatServlet.handleDeleteAction - Document could not be deleted: "
1591
                        + e.getMessage());
1592
            }
1593
        }
1594
    }
1595
    
1596
    /**
1597
     * Handle the validation request and return the results to the requestor
1598
     */
1599
    protected void handleValidateAction(PrintWriter out, Hashtable<String, String[]> params) {
1600
        
1601
        // Get the document indicated
1602
        String valtext = null;
1603
        DBConnection dbConn = null;
1604
        int serialNumber = -1;
1605
        
1606
        try {
1607
            valtext = params.get("valtext")[0];
1608
        } catch (Exception nullpe) {
1609
            
1610
            String docid = null;
1611
            try {
1612
                // Find the document id number
1613
                docid = params.get("docid")[0];
1614
                
1615
                // Get the document indicated from the db
1616
                DocumentImpl xmldoc = new DocumentImpl(docid);
1617
                valtext = xmldoc.toString();
1618
                
1619
            } catch (NullPointerException npe) {
1620
                
1621
                out.println("<error>Error getting document ID: " + docid
1622
                        + "</error>");
1623
                //if ( conn != null ) { util.returnConnection(conn); }
1624
                return;
1625
            } catch (Exception e) {
1626
                
1627
                out.println(e.getMessage());
1628
            }
1629
        }
1630
        
1631
        try {
1632
            // get a connection from the pool
1633
            dbConn = DBConnectionPool
1634
                    .getDBConnection("MetaCatServlet.handleValidateAction");
1635
            serialNumber = dbConn.getCheckOutSerialNumber();
1636
            DBValidate valobj = new DBValidate(dbConn);
1637
//            boolean valid = valobj.validateString(valtext);
1638
            
1639
            // set content type and other response header fields first
1640
            
1641
            out.println(valobj.returnErrors());
1642
            
1643
        } catch (NullPointerException npe2) {
1644
            // set content type and other response header fields first
1645
            
1646
            out.println("<error>Error validating document.</error>");
1647
        } catch (Exception e) {
1648
            
1649
            out.println(e.getMessage());
1650
        } finally {
1651
            // Return db connection
1652
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1653
        }
1654
    }
1655
    
1656
    /**
1657
     * Handle "getrevsionanddoctype" action Given a docid, return it's current
1658
     * revision and doctype from data base The output is String look like
1659
     * "rev;doctype"
1660
     */
1661
    protected void handleGetRevisionAndDocTypeAction(PrintWriter out,
1662
            Hashtable<String, String[]> params) {
1663
        // To store doc parameter
1664
        String[] docs = new String[10];
1665
        // Store a single doc id
1666
        String givenDocId = null;
1667
        // Get docid from parameters
1668
        if (params.containsKey("docid")) {
1669
            docs = params.get("docid");
1670
        }
1671
        // Get first docid form string array
1672
        givenDocId = docs[0];
1673
        
1674
        try {
1675
            // Make sure there is a docid
1676
            if (givenDocId == null || givenDocId.equals("")) { throw new Exception(
1677
                    "User didn't specify docid!"); }//if
1678
            
1679
            // Create a DBUtil object
1680
            DBUtil dbutil = new DBUtil();
1681
            // Get a rev and doctype
1682
            String revAndDocType = dbutil
1683
                    .getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
1684
            out.println(revAndDocType);
1685
            
1686
        } catch (Exception e) {
1687
            // Handle exception
1688
            out.println("<?xml version=\"1.0\"?>");
1689
            out.println("<error>");
1690
            out.println(e.getMessage());
1691
            out.println("</error>");
1692
        }
1693
        
1694
    }
1695
    
1696
    /**
1697
     * Handle "getaccesscontrol" action. Read Access Control List from db
1698
     * connection in XML format
1699
     */
1700
    protected void handleGetAccessControlAction(PrintWriter out,
1701
            Hashtable<String,String[]> params, HttpServletResponse response, String username,
1702
            String[] groupnames) {
1703
        
1704
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1705

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

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

    
2872
    /**
2873
     * @param sitemapScheduled toggle the _sitemapScheduled flag
2874
     */
2875
    public static void set_sitemapScheduled(boolean sitemapScheduled) {
2876
        _sitemapScheduled = sitemapScheduled;
2877
    }
2878

    
2879
}
(43-43/62)