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.ByteArrayInputStream;
29
import java.io.File;
30
import java.io.FileInputStream;
31
import java.io.IOException;
32
import java.io.InputStreamReader;
33
import java.io.OutputStream;
34
import java.io.OutputStreamWriter;
35
import java.io.PrintWriter;
36
import java.io.Reader;
37
import java.io.StringReader;
38
import java.io.ByteArrayOutputStream;
39
import java.io.UnsupportedEncodingException;
40
import java.io.Writer;
41
import java.net.MalformedURLException;
42
import java.net.URL;
43
import java.sql.PreparedStatement;
44
import java.sql.ResultSet;
45
import java.sql.SQLException;
46
import java.sql.Timestamp;
47
import java.text.ParseException;
48
import java.text.SimpleDateFormat;
49
import java.util.Enumeration;
50
import java.util.HashMap;
51
import java.util.Hashtable;
52
import java.util.Iterator;
53
import java.util.Map;
54
import java.util.Timer;
55
import java.util.Vector;
56
import java.util.zip.ZipEntry;
57
import java.util.zip.ZipOutputStream;
58

    
59
import javax.servlet.ServletOutputStream;
60
import javax.servlet.http.HttpServletRequest;
61
import javax.servlet.http.HttpServletResponse;
62
import javax.servlet.http.HttpSession;
63
import javax.activation.MimetypesFileTypeMap;
64

    
65
import org.apache.commons.io.input.XmlStreamReader;
66
import org.apache.log4j.Logger;
67
import org.ecoinformatics.eml.EMLParser;
68

    
69
import au.com.bytecode.opencsv.CSVWriter;
70

    
71
import com.oreilly.servlet.multipart.FilePart;
72
import com.oreilly.servlet.multipart.MultipartParser;
73
import com.oreilly.servlet.multipart.ParamPart;
74
import com.oreilly.servlet.multipart.Part;
75

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

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

    
115
    private static boolean _sitemapScheduled = false;
116
    
117
    private static Logger logMetacat = Logger.getLogger(MetacatHandler.class);
118

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

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

    
484
        if (runTime > squeryWarnLimit) {
485
            logMetacat.warn("MetaCatServlet.handleSQuery - Long running squery.  Total time: " + runTime + 
486
                    " ms, squery: " + ((String[])params.get("query"))[0]);
487
        }
488
        logMetacat.debug("MetaCatServlet.handleSQuery - squery: " + ((String[])params.get("query"))[0] + 
489
                " ran in " + runTime + " ms");
490
    }
491
    
492
    /**
493
     * Create the xml query, execute it and display the results.
494
     *
495
     * @param out the output stream to the client
496
     * @param params the Hashtable of parameters that should be included in the
497
     *            squery.
498
     * @param response the response object linked to the client
499
     * @throws IOException 
500
     * @throws UnsupportedEncodingException 
501
     */
502
    protected void handleQuery(Writer out, Hashtable<String, String[]> params,
503
            HttpServletResponse response, String user, String[] groups,
504
            String sessionid) throws PropertyNotFoundException, UnsupportedEncodingException, IOException {
505
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
506
        long queryWarnLimit = Long.parseLong(PropertyService.getProperty("database.queryTimeWarnLimit"));
507
        
508
        //create the query and run it
509
        String xmlquery = DBQuery.createSQuery(params);
510
        String[] queryArray = new String[1];
511
        queryArray[0] = xmlquery;
512
        params.put("query", queryArray);
513
        long startTime = System.currentTimeMillis();
514
        DBQuery queryobj = new DBQuery();
515
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
516
        long outPutTime = System.currentTimeMillis();
517
        long runTime = outPutTime -startTime;
518

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

    
1030
                    // Set the output filename on the response
1031
                    String outputname = generateOutputName(docid, params, doc);                    
1032
                    response.setHeader("Content-Disposition",
1033
                            "attachment; filename=\"" + outputname + "\"");
1034
                }
1035
                
1036
                // Write the data to the output stream
1037
                try {
1038
                    byte[] buf = new byte[4 * 1024]; // 4K buffer
1039
                    int b = fin.read(buf);
1040
                    while (b != -1) {
1041
                        out.write(buf, 0, b);
1042
                        b = fin.read(buf);
1043
                    }
1044
                } finally {
1045
                    if (fin != null) fin.close();
1046
                }
1047
                
1048
            } else {
1049
                // this is metadata doc
1050
                if (qformat.equals("xml") || qformat.equals("")) {
1051
                    // if equals "", that means no qformat is specified. hence
1052
                    // by default the document should be returned in xml format
1053
                    // set content type first
1054
                    
1055
                    if (response != null) {
1056
                        response.setContentType("text/xml"); //MIME type
1057
                        response.setHeader("Content-Disposition",
1058
                                "attachment; filename=" + docid + ".xml");
1059
                    }
1060
                    
1061
                    // Try to get the metadata file from disk. If it isn't
1062
                    // found, create it from the db and write it to disk then.
1063
                    try {
1064
                        doc.toXml(out, user, groups, withInlineData);               
1065
                    } catch (McdbException e) {
1066
                        // any exceptions in reading the xml from disc, and we go back to the
1067
                        // old way of creating the xml directly.
1068
                        logMetacat.error("MetaCatServlet.readFromMetacat - could not read from document file " + docid 
1069
                                + ": " + e.getMessage());
1070
                        e.printStackTrace(System.out);
1071
                        doc.toXmlFromDb(out, user, groups, withInlineData);
1072
                    }
1073
                } else {
1074
                    // TODO MCD, this should read from disk as well?
1075
                    //*** This is a metadata doc, to be returned in a skin/custom format.
1076
                    //*** Add param to indicate if public has read access or not.
1077
                    logMetacat.debug("User: \n" + user);
1078
                    if (!user.equals("public")) {
1079
                        if (DocumentImpl.hasReadPermission("public", null, docid))
1080
                            params.put("publicRead", new String[] {"true"});
1081
                        else
1082
                            params.put("publicRead", new String[] {"false"});
1083
                    }
1084
                    
1085
                    if (response != null) {
1086
                        response.setContentType("text/html"); //MIME type
1087
                    }
1088
                    
1089
                    // detect actual encoding
1090
                    String docString = doc.toString(user, groups, withInlineData);
1091
                    XmlStreamReader xsr = new XmlStreamReader(new ByteArrayInputStream(doc.getBytes()));
1092
        			String encoding = xsr.getEncoding();
1093
                    Writer w = null;
1094
        			if (encoding != null) {
1095
        				w = new OutputStreamWriter(out, encoding);
1096
        			} else {
1097
                        w = new OutputStreamWriter(out);
1098
        			}
1099

    
1100
                    // Look up the document type
1101
                    String doctype = doc.getDoctype();
1102
                    // Transform the document to the new doctype
1103
                    DBTransform dbt = new DBTransform();
1104
                    dbt.transformXMLDocument(
1105
                    		docString, 
1106
                    		doctype, "-//W3C//HTML//EN",
1107
                            qformat, 
1108
                            w, 
1109
                            params, 
1110
                            null);
1111
                }
1112
                
1113
            }
1114
            EventLog.getInstance().log(ipAddress, user, docid, "read");
1115
        } catch (PropertyNotFoundException except) {
1116
            throw except;
1117
        }
1118
    }
1119

    
1120
    /**
1121
     * Create a filename to be used for naming a downloaded document
1122
     * @param docid the identifier of the document to be named
1123
     * @param params the parameters of the request
1124
     * @param doc the DocumentImpl of the document to be named
1125
     * @return String containing a name for the download
1126
     */
1127
    private String generateOutputName(String docid,
1128
            Hashtable<String, String[]> params, DocumentImpl doc) {
1129
        String outputname = null;
1130
        // check for the existence of a metadatadocid parameter,
1131
        // if this is sent, then send a filename which contains both
1132
        // the metadata docid and the data docid, so the link with
1133
        // metadata is explicitly encoded in the filename.
1134
        String metadatadocid = null;
1135
        Vector<String> nameparts = new Vector<String>();
1136

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

    
1521
                        EventLog.getInstance().log(ipAddress, user, accNumber, action[0]);
1522
                    }
1523
                } finally {
1524
                    // Return db connection
1525
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1526
                }
1527
                
1528
                // set content type and other response header fields first
1529
                //response.setContentType("text/xml");
1530
                output += "<?xml version=\"1.0\"?>";
1531
                output += "<success>";
1532
                output += "<docid>" + newdocid + "</docid>";
1533
                output += "</success>";
1534
                
1535
            } catch (NullPointerException npe) {
1536
                //response.setContentType("text/xml");
1537
                output += "<?xml version=\"1.0\"?>";
1538
                output += "<error>";
1539
                output += npe.getMessage();
1540
                output += "</error>";
1541
                logMetacat.warn("MetaCatServlet.handleInsertOrUpdateAction - Null pointer error when writing eml document to the database: " + npe.getMessage());
1542
                npe.printStackTrace();
1543
            }
1544
        } catch (Exception e) {
1545
            //response.setContentType("text/xml");
1546
            output += "<?xml version=\"1.0\"?>";
1547
            output += "<error>";
1548
            output += e.getMessage();
1549
            output += "</error>";
1550
            logMetacat.warn("MetaCatServlet.handleInsertOrUpdateAction - General error when writing eml document to the database: " + e.getMessage());
1551
            e.printStackTrace();
1552
        }
1553
        
1554
        if (qformat == null || qformat.equals("xml")) {
1555
            if(response != null)
1556
            {
1557
              response.setContentType("text/xml");
1558
              out.println(output);
1559
            }
1560
            return output;
1561
        } else {
1562
            try {
1563
                DBTransform trans = new DBTransform();
1564
                response.setContentType("text/html");
1565
                trans.transformXMLDocument(output,
1566
                        "message", "-//W3C//HTML//EN", qformat,
1567
                        out, null, null);
1568
            } catch (Exception e) {
1569
                
1570
                logMetacat.error("MetaCatServlet.handleInsertOrUpdateAction - General error: "
1571
                        + e.getMessage());
1572
                e.printStackTrace(System.out);
1573
            }
1574
        }
1575
        return null;
1576
    }
1577
    
1578
    /**
1579
     * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > in
1580
     * order to decide whether to use validation parser
1581
     */
1582
    private static boolean needDTDValidation(StringReader xmlreader)
1583
    throws IOException {
1584
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1585
        StringBuffer cbuff = new StringBuffer();
1586
        java.util.Stack<String> st = new java.util.Stack<String>();
1587
        boolean validate = false;
1588
        boolean commented = false;
1589
        int c;
1590
        int inx;
1591
        
1592
        // read from the stream until find the keywords
1593
        while ((st.empty() || st.size() < 4) && ((c = xmlreader.read()) != -1)) {
1594
            cbuff.append((char) c);
1595
            
1596
            if ((inx = cbuff.toString().indexOf("<!--")) != -1) {
1597
                commented = true;
1598
            }
1599
            
1600
            // "<!DOCTYPE" keyword is found; put it in the stack
1601
            if ((inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1) {
1602
                cbuff = new StringBuffer();
1603
                st.push("<!DOCTYPE");
1604
            }
1605
            // "PUBLIC" keyword is found; put it in the stack
1606
            if ((inx = cbuff.toString().indexOf("PUBLIC")) != -1) {
1607
                cbuff = new StringBuffer();
1608
                st.push("PUBLIC");
1609
            }
1610
            // "SYSTEM" keyword is found; put it in the stack
1611
            if ((inx = cbuff.toString().indexOf("SYSTEM")) != -1) {
1612
                cbuff = new StringBuffer();
1613
                st.push("SYSTEM");
1614
            }
1615
            // ">" character is found; put it in the stack
1616
            // ">" is found twice: fisrt from <?xml ...?>
1617
            // and second from <!DOCTYPE ... >
1618
            if ((inx = cbuff.toString().indexOf(">")) != -1) {
1619
                cbuff = new StringBuffer();
1620
                st.push(">");
1621
            }
1622
        }
1623
        
1624
        // close the stream
1625
        xmlreader.reset();
1626
        
1627
        // check the stack whether it contains the keywords:
1628
        // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1629
        if (st.size() == 4) {
1630
            if ((st.pop()).equals(">")
1631
            && ((st.peek()).equals("PUBLIC") | (st.pop()).equals("SYSTEM"))
1632
                    && (st.pop()).equals("<!DOCTYPE")) {
1633
                validate = true && !commented;
1634
            }
1635
        }
1636
        
1637
        logMetacat.info("MetaCatServlet.needDTDValidation - Validation for dtd is " + validate);
1638
        return validate;
1639
    }
1640
    
1641
    // END OF INSERT/UPDATE SECTION
1642
    
1643
    /**
1644
     * Handle the database delete request and delete an XML document from the
1645
     * database connection
1646
     */
1647
    public void handleDeleteAction(PrintWriter out, Hashtable<String, String[]> params,
1648
            HttpServletRequest request, HttpServletResponse response,
1649
            String user, String[] groups) {
1650
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1651
        String[] docid = params.get("docid");
1652
        
1653
        if(docid == null){
1654
            response.setContentType("text/xml");
1655
            out.println("<?xml version=\"1.0\"?>");
1656
            out.println("<error>");
1657
            out.println("Docid not specified.");
1658
            out.println("</error>");
1659
            logMetacat.error("MetaCatServlet.handleDeleteAction - Docid not specified for the document to be deleted.");
1660
        } else {
1661
            
1662
            // delete the document from the database
1663
            try {
1664
                
1665
                try {
1666
                    // null means notify server is null
1667
                    DocumentImpl.delete(docid[0], user, groups, null);
1668
                    EventLog.getInstance().log(request.getRemoteAddr(),
1669
                            user, docid[0], "delete");
1670
                    response.setContentType("text/xml");
1671
                    out.println("<?xml version=\"1.0\"?>");
1672
                    out.println("<success>");
1673
                    out.println("Document deleted.");
1674
                    out.println("</success>");
1675
                    logMetacat.info("MetaCatServlet.handleDeleteAction - Document deleted.");
1676
                    
1677
                    // Delete from spatial cache if runningSpatialOption
1678
                    if ( PropertyService.getProperty("spatial.runSpatialOption").equals("true") ) {
1679
                        SpatialHarvester sh = new SpatialHarvester();
1680
                        sh.addToDeleteQue( DocumentUtil.getSmartDocId( docid[0] ) );
1681
                        sh.destroy();
1682
                    }
1683
                    
1684
                } catch (AccessionNumberException ane) {
1685
                    response.setContentType("text/xml");
1686
                    out.println("<?xml version=\"1.0\"?>");
1687
                    out.println("<error>");
1688
                    //out.println("Error deleting document!!!");
1689
                    out.println(ane.getMessage());
1690
                    out.println("</error>");
1691
                    logMetacat.error("MetaCatServlet.handleDeleteAction - Document could not be deleted: "
1692
                            + ane.getMessage());
1693
                    ane.printStackTrace(System.out);
1694
                }
1695
            } catch (Exception e) {
1696
                response.setContentType("text/xml");
1697
                out.println("<?xml version=\"1.0\"?>");
1698
                out.println("<error>");
1699
                out.println(e.getMessage());
1700
                out.println("</error>");
1701
                logMetacat.error("MetaCatServlet.handleDeleteAction - Document could not be deleted: "
1702
                        + e.getMessage());
1703
                e.printStackTrace(System.out);
1704
            }
1705
        }
1706
    }
1707
    
1708
    /**
1709
     * Handle the validation request and return the results to the requestor
1710
     */
1711
    protected void handleValidateAction(PrintWriter out, Hashtable<String, String[]> params) {
1712
        
1713
        // Get the document indicated
1714
        String valtext = null;
1715
        DBConnection dbConn = null;
1716
        int serialNumber = -1;
1717
        
1718
        try {
1719
            valtext = params.get("valtext")[0];
1720
        } catch (Exception nullpe) {
1721
            
1722
            String docid = null;
1723
            try {
1724
                // Find the document id number
1725
                docid = params.get("docid")[0];
1726
                
1727
                // Get the document indicated from the db
1728
                DocumentImpl xmldoc = new DocumentImpl(docid, false);
1729
                valtext = xmldoc.toString();
1730
                
1731
            } catch (NullPointerException npe) {
1732
                
1733
                out.println("<error>Error getting document ID: " + docid
1734
                        + "</error>");
1735
                //if ( conn != null ) { util.returnConnection(conn); }
1736
                return;
1737
            } catch (Exception e) {
1738
                
1739
                out.println(e.getMessage());
1740
            }
1741
        }
1742
        
1743
        try {
1744
            // get a connection from the pool
1745
            dbConn = DBConnectionPool
1746
                    .getDBConnection("MetaCatServlet.handleValidateAction");
1747
            serialNumber = dbConn.getCheckOutSerialNumber();
1748
            DBValidate valobj = new DBValidate(dbConn);
1749
//            boolean valid = valobj.validateString(valtext);
1750
            
1751
            // set content type and other response header fields first
1752
            
1753
            out.println(valobj.returnErrors());
1754
            
1755
        } catch (NullPointerException npe2) {
1756
            // set content type and other response header fields first
1757
            
1758
            out.println("<error>Error validating document.</error>");
1759
        } catch (Exception e) {
1760
            
1761
            out.println(e.getMessage());
1762
        } finally {
1763
            // Return db connection
1764
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1765
        }
1766
    }
1767
    
1768
    /**
1769
     * Handle "getrevsionanddoctype" action Given a docid, return it's current
1770
     * revision and doctype from data base The output is String look like
1771
     * "rev;doctype"
1772
     */
1773
    protected void handleGetRevisionAndDocTypeAction(PrintWriter out,
1774
            Hashtable<String, String[]> params) {
1775
        // To store doc parameter
1776
        String[] docs = new String[10];
1777
        // Store a single doc id
1778
        String givenDocId = null;
1779
        // Get docid from parameters
1780
        if (params.containsKey("docid")) {
1781
            docs = params.get("docid");
1782
        }
1783
        // Get first docid form string array
1784
        givenDocId = docs[0];
1785
        
1786
        try {
1787
            // Make sure there is a docid
1788
            if (givenDocId == null || givenDocId.equals("")) { throw new Exception(
1789
                    "User didn't specify docid!"); }//if
1790
            
1791
            // Create a DBUtil object
1792
            DBUtil dbutil = new DBUtil();
1793
            // Get a rev and doctype
1794
            String revAndDocType = dbutil
1795
                    .getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
1796
            out.println(revAndDocType);
1797
            
1798
        } catch (Exception e) {
1799
            // Handle exception
1800
            out.println("<?xml version=\"1.0\"?>");
1801
            out.println("<error>");
1802
            out.println(e.getMessage());
1803
            out.println("</error>");
1804
        }
1805
        
1806
    }
1807
    
1808
    /**
1809
     * Handle "getaccesscontrol" action. Read Access Control List from db
1810
     * connection in XML format
1811
     */
1812
    protected void handleGetAccessControlAction(PrintWriter out,
1813
            Hashtable<String,String[]> params, HttpServletResponse response, String username,
1814
            String[] groupnames) {
1815
        
1816
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1817

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

    
2531
        /*
2532
         * response.setContentType("text/xml"); try { out =
2533
         * response.getWriter(); } catch (IOException ioe2) {
2534
         * System.err.println("Fatal Error: couldn't get response output
2535
         * stream.");
2536
         */
2537

    
2538
        if (params.containsKey("docid")) {
2539
            docid = params.get("docid")[0];
2540
        }
2541

    
2542
        if(params.containsKey("qformat")) {
2543
            qformat = params.get("qformat")[0];
2544
        }
2545

    
2546
        // Make sure we have a docid and datafile
2547
        if (docid != null && fileList.containsKey("datafile")) {
2548
            logMetacat.info("MetaCatServlet.handleUploadAction - Uploading data docid: " + docid);
2549
            // Get a reference to the file part of the form
2550
            //FilePart filePart = (FilePart) fileList.get("datafile");
2551
            String fileName = fileList.get("filename");
2552
            logMetacat.info("MetaCatServlet.handleUploadAction - Uploading filename: " + fileName);
2553
            // Check if the right file existed in the uploaded data
2554
            if (fileName != null) {
2555

    
2556
                try {
2557
                    //logMetacat.info("Upload datafile " + docid
2558
                    // +"...", 10);
2559
                    //If document get lock data file grant
2560
                    if (DocumentImpl.getDataFileLockGrant(docid)) {
2561
                        // Save the data file to disk using "docid" as the name
2562
                        String datafilepath = PropertyService.getProperty("application.datafilepath");
2563
                        File dataDirectory = new File(datafilepath);
2564
                        dataDirectory.mkdirs();
2565
                        File newFile = null;
2566
                        //                    File tempFile = null;
2567
                        String tempFileName = fileList.get("name");
2568
                        String newFileName = dataDirectory + File.separator + docid;
2569
                        long size = 0;
2570
                        boolean fileExists = false;
2571

    
2572
                        try {
2573
                            newFile = new File(newFileName);
2574
                            fileExists = newFile.exists();
2575
                            logMetacat.info("MetaCatServlet.handleUploadAction - new file status is: " + fileExists);
2576
                            if ( fileExists == false ) {
2577
                                // copy file to desired output location
2578
                                try {
2579
                                    MetacatUtil.copyFile(tempFileName, newFileName);
2580
                                } catch (IOException ioe) {
2581
                                    logMetacat.error("IO Exception copying file: " +
2582
                                            ioe.getMessage());
2583
                                    ioe.printStackTrace(System.out);
2584
                                }
2585
                                size = newFile.length();
2586
                                if (size == 0) {
2587
                                    throw new IOException("Uploaded file is 0 bytes!");
2588
                                }
2589
                            } // Latent bug here if the file already exists, then the
2590
                              // conditional fails but the document is still registered.
2591
                              // maybe this never happens because we already requested a lock?
2592
                            logMetacat.info("MetaCatServlet.handleUploadAction - Uploading the following to Metacat:" +
2593
                                    fileName + ", " + docid + ", " +
2594
                                    username + ", " + groupnames);
2595
                            //register the file in the database (which generates
2596
                            // an exception
2597
                            //if the docid is not acceptable or other untoward
2598
                            // things happen
2599
                            DocumentImpl.registerDocument(fileName, "BIN", docid,
2600
                                    username, groupnames);
2601
                        } catch (Exception ee) {
2602
                            // If the file did not exist before this method was 
2603
                            // called and an exception is generated while 
2604
                            // creating or registering it, then we want to delete
2605
                            // the file from disk because the operation failed.
2606
                            // However, if the file already existed before the 
2607
                            // method was called, then the exception probably
2608
                            // occurs when registering the document, and so we
2609
                            // want to leave the old file in place.
2610
                            if ( fileExists == false ) {
2611
                                newFile.delete();
2612
                            }
2613
                            
2614
                            logMetacat.info("MetaCatServlet.handleUploadAction - in Exception: fileExists is " + fileExists);
2615
                            logMetacat.error("MetaCatServlet.handleUploadAction - Upload Error: " + ee.getMessage());
2616
                            throw ee;
2617
                        }
2618

    
2619
                        EventLog.getInstance().log(request.getRemoteAddr(),
2620
                                username, docid, "upload");
2621
                        // Force replication this data file
2622
                        // To data file, "insert" and update is same
2623
                        // The fourth parameter is null. Because it is
2624
                        // notification server
2625
                        // and this method is in MetaCatServerlet. It is
2626
                        // original command,
2627
                        // not get force replication info from another metacat
2628
                        ForceReplicationHandler frh = new ForceReplicationHandler(
2629
                                docid, "insert", false, null);
2630
                        logMetacat.debug("MetaCatServlet.handleUploadAction - ForceReplicationHandler created: " + frh.toString());
2631

    
2632
                        // set content type and other response header fields
2633
                        // first
2634
                        output += "<?xml version=\"1.0\"?>";
2635
                        output += "<success>";
2636
                        output += "<docid>" + docid + "</docid>";
2637
                        output += "<size>" + size + "</size>";
2638
                        output += "</success>";
2639
                    }
2640

    
2641
                } catch (Exception e) {
2642

    
2643
                    output += "<?xml version=\"1.0\"?>";
2644
                    output += "<error>";
2645
                    output += e.getMessage();
2646
                    output += "</error>";
2647
                }
2648
            } else {
2649
                // the field did not contain a file
2650
                output += "<?xml version=\"1.0\"?>";
2651
                output += "<error>";
2652
                output += "The uploaded data did not contain a valid file.";
2653
                output += "</error>";
2654
            }
2655
        } else {
2656
            // Error bcse docid missing or file missing
2657
            output += "<?xml version=\"1.0\"?>";
2658
            output += "<error>";
2659
            output += "The uploaded data did not contain a valid docid "
2660
                + "or valid file.";
2661
            output += "</error>";
2662
        }
2663

    
2664
        if (qformat == null || qformat.equals("xml")) {
2665
            response.setContentType("text/xml");
2666
            out.println(output);
2667
        } else {
2668
            try {
2669
                DBTransform trans = new DBTransform();
2670
                response.setContentType("text/html");
2671
                trans.transformXMLDocument(output,
2672
                        "message", "-//W3C//HTML//EN", qformat,
2673
                        out, null, null);
2674
            } catch (Exception e) {
2675

    
2676
                logMetacat.error("MetaCatServlet.handleUploadAction - General error: "
2677
                        + e.getMessage());
2678
                e.printStackTrace(System.out);
2679
            }
2680
        }
2681
    }
2682
    
2683
    /*
2684
     * A method to handle set access action
2685
     */
2686
    protected void handleSetAccessAction(PrintWriter out, Hashtable<String, String[]> params,
2687
            String username, HttpServletRequest request, HttpServletResponse response) {
2688
        
2689
        String permission = null;
2690
        String permType = null;
2691
        String permOrder = null;
2692
        Vector<String> errorList = new Vector<String>();
2693
        String error = null;
2694
        Vector<String> successList = new Vector<String>();
2695
        String success = null;
2696
        boolean isEmlPkgMember = false;
2697
        
2698
        String[] docList = params.get("docid");
2699
        String[] principalList = params.get("principal");
2700
        String[] permissionList = params.get("permission");
2701
        String[] permTypeList = params.get("permType");
2702
        String[] permOrderList = params.get("permOrder");
2703
        String[] qformatList = params.get("qformat");
2704
        String[] accessBlock = params.get("accessBlock");
2705
        if(accessBlock != null) {
2706
            if (docList == null) {
2707
                errorList.addElement("MetaCatServlet.handleSetAccessAction - Doc id missing.  Please check your parameter list, it should look like: "
2708
                    + "?action=setaccess&docid=<doc_id>&accessBlock=<access_section>");
2709
                outputResponse(successList, errorList, out);
2710
                return;
2711
            }
2712
            try {
2713
                AccessControlForSingleFile accessControl = 
2714
                    new AccessControlForSingleFile(docList[0]);
2715
                accessControl.insertPermissions(accessBlock[0]);
2716
                successList.addElement("MetaCatServlet.handleSetAccessAction - successfully replaced access block for doc id: " + docList[0]);
2717
            } catch(AccessControlException ace) {
2718
                errorList.addElement("MetaCatServlet.handleSetAccessAction - access control error when setting " + 
2719
                    "access block: " + ace.getMessage());
2720
            }
2721
            outputResponse(successList, errorList, out);
2722
            return;
2723
        }
2724
        
2725
        // Make sure the parameter is not null
2726
        if (docList == null || principalList == null || permTypeList == null
2727
                || permissionList == null) {
2728
            error = "MetaCatServlet.handleSetAccessAction - Please check your parameter list, it should look like: "
2729
                    + "?action=setaccess&docid=pipeline.1.1&principal=public"
2730
                    + "&permission=read&permType=allow&permOrder=allowFirst";
2731
            errorList.addElement(error);
2732
            outputResponse(successList, errorList, out);
2733
            return;
2734
        }
2735
        
2736
        // Only select first element for permission, type and order
2737
        permission = permissionList[0];
2738
        permType = permTypeList[0];
2739
        System.out.println("permission in MetacatHandler.handleSetAccessAction: " + permission);
2740
        
2741
        if (permOrderList != null) {
2742
            permOrder = permOrderList[0];
2743
        }
2744
        
2745
        // Get package doctype set
2746
        Vector<String> packageSet = null;
2747
        try {
2748
            packageSet = 
2749
                MetacatUtil.getOptionList(PropertyService.getProperty("xml.packagedoctypeset"));
2750
        } catch (PropertyNotFoundException pnfe) {
2751
            logMetacat.error("MetaCatServlet.handleSetAccessAction - Could not find package doctype set.  Setting to null: " 
2752
                    + pnfe.getMessage());
2753
        }
2754
        //debug
2755
        if (packageSet != null) {
2756
            for (int i = 0; i < packageSet.size(); i++) {
2757
                logMetacat.debug("MetaCatServlet.handleSetAccessAction - doctype in package set: "
2758
                        + packageSet.elementAt(i));
2759
            }
2760
        }
2761
        
2762
        // handle every accessionNumber
2763
        for (int i = 0; i < docList.length; i++) {
2764
            String docid = docList[i];
2765
            if (docid.startsWith("urn:")) {
2766
                try {
2767
                    String actualDocId = LSIDUtil.getDocId(docid, false);
2768
                    docid = actualDocId;
2769
                } catch (ParseLSIDException ple) {
2770
                    logMetacat.error("MetaCatServlet.handleSetAccessAction - " +
2771
                            "could not parse lsid: " + docid + " : " + ple.getMessage()); 
2772
                    ple.printStackTrace(System.out);
2773
                }
2774
            }
2775
            String accessionNumber = docid;
2776
            String owner = null;
2777
            String publicId = null;
2778
            // Get document owner and public id
2779
            try {
2780
                owner = getFieldValueForDoc(accessionNumber, "user_owner");
2781
                publicId = getFieldValueForDoc(accessionNumber, "doctype");
2782
            } catch (Exception e) {
2783
                logMetacat.error("MetaCatServlet.handleSetAccessAction - Error in handleSetAccessAction: "
2784
                        + e.getMessage());
2785
                e.printStackTrace(System.out);
2786
                error = "Error in set access control for document - " + accessionNumber + e.getMessage();
2787
                errorList.addElement(error);
2788
                continue;
2789
            }
2790
            //check if user is the owner. Only owner can do owner
2791
            if (username == null || owner == null || !username.equals(owner)) {
2792
                error = "User - " + username + " does not have permission to set "
2793
                        + "access control for docid - " + accessionNumber;
2794
                errorList.addElement(error);
2795
                System.out.println("user " + username + " does not have permission to set " + 
2796
                        "access control for docid " + accessionNumber);
2797
                continue;
2798
            }
2799
            
2800
            //*** Find out if the document is a Member of an EML package.
2801
            //*** (for efficiency, only check if it isn't already true
2802
            //*** for the case of multiple files).
2803
            if (isEmlPkgMember == false)
2804
                isEmlPkgMember = (DBUtil.findDataSetDocIdForGivenDocument(accessionNumber) != null);
2805
            
2806
            // If docid publicid is BIN data file or other beta4, 6 package document
2807
            // we could not do set access control. Because we don't want inconsistent
2808
            // to its access docuemnt
2809
            if (publicId != null && packageSet != null
2810
                    && packageSet.contains(publicId) && isEmlPkgMember) {
2811
                error = "Could not set access control to document " + accessionNumber
2812
                        + "because it is in a pakcage and it has a access file for it";
2813
                errorList.addElement(error);
2814
                System.out.println("this is a beta4 or 6 document so we can't set the access element.");
2815
                continue;
2816
            }
2817
            // for every principle
2818
            for (int j = 0; j < principalList.length; j++) {
2819
                String principal = principalList[j];
2820
                try {
2821
                    //insert permission
2822
                    AccessControlForSingleFile accessControl = 
2823
                        new AccessControlForSingleFile(accessionNumber);
2824
                    //System.out.println("permission in MetacatHandler: " + l.longValue());
2825
                    //System.out.println("permission in MetacatHandler: " + Integer.valueOf(AccessControlList.intValue(permission)).longValue());
2826
                    accessControl.insertPermissions(principal, Integer.valueOf(AccessControlList.intValue(permission)).longValue(), permType, permOrder);
2827
                } catch (Exception ee) {
2828
                    logMetacat.error("MetaCatServlet.handleSetAccessAction - Error inserting permission: "
2829
                            + ee.getMessage());
2830
                    ee.printStackTrace(System.out);
2831
                    error = "Failed to set access control for document "
2832
                            + accessionNumber + " because " + ee.getMessage();
2833
                    errorList.addElement(error);
2834
                    continue;
2835
                }
2836
            }
2837
            //force replication when this action is called
2838
            boolean isXml = true;
2839
            if (publicId.equalsIgnoreCase("BIN")) {
2840
                isXml = false;
2841
            }
2842
            ForceReplicationHandler frh = 
2843
                new ForceReplicationHandler(accessionNumber, isXml, null);
2844
            logMetacat.debug("MetaCatServlet.handleSetAccessAction - ForceReplicationHandler created: " + frh.toString());
2845
            
2846
        }
2847
        if (errorList.isEmpty()) {
2848
        	successList.addElement("MetaCatServlet.handleSetAccessAction - successfully added individual access for doc id: " + docList[0]);
2849
        }
2850
        if (params.get("forwardto")  != null) {
2851
            try {
2852
                RequestUtil.forwardRequest(request, response, params);
2853
            } catch (MetacatUtilException mue) {
2854
                logMetacat.error("metaCatServlet.handleSetAccessAction - could not forward " +
2855
                        "request. Sending output to response writer");
2856
                mue.printStackTrace(System.out);
2857
                outputResponse(successList, errorList, out);
2858
            }               
2859
        } else {
2860
            outputResponse(successList, errorList, out);
2861
        }
2862
    }
2863
    
2864
    /*
2865
     * A method try to determin a docid's public id, if couldn't find null will
2866
     * be returned.
2867
     */
2868
    private String getFieldValueForDoc(String accessionNumber, String fieldName)
2869
    throws Exception {
2870
        if (accessionNumber == null || accessionNumber.equals("")
2871
        || fieldName == null || fieldName.equals("")) { throw new Exception(
2872
                "Docid or field name was not specified"); }
2873
        
2874
        PreparedStatement pstmt = null;
2875
        ResultSet rs = null;
2876
        String fieldValue = null;
2877
        String docId = null;
2878
        DBConnection conn = null;
2879
        int serialNumber = -1;
2880
        
2881
        // get rid of revision if access number has
2882
        docId = DocumentUtil.getDocIdFromString(accessionNumber);
2883
        try {
2884
            //check out DBConnection
2885
            conn = DBConnectionPool
2886
                    .getDBConnection("MetaCatServlet.getPublicIdForDoc");
2887
            serialNumber = conn.getCheckOutSerialNumber();
2888
            pstmt = conn.prepareStatement("SELECT " + fieldName
2889
                    + " FROM xml_documents " + "WHERE docid = ? ");
2890
            
2891
            pstmt.setString(1, docId);
2892
            pstmt.execute();
2893
            rs = pstmt.getResultSet();
2894
            boolean hasRow = rs.next();
2895
        //    int perm = 0;
2896
            if (hasRow) {
2897
                fieldValue = rs.getString(1);
2898
            } else {
2899
                throw new Exception("Could not find document: "
2900
                        + accessionNumber);
2901
            }
2902
        } catch (Exception e) {
2903
            logMetacat.error("MetaCatServlet.getFieldValueForDoc - General error: "
2904
                    + e.getMessage());
2905
            throw e;
2906
        } finally {
2907
            try {
2908
                rs.close();
2909
                pstmt.close();
2910
                
2911
            } finally {
2912
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2913
            }
2914
        }
2915
        return fieldValue;
2916
    }
2917
    
2918
    /*
2919
     * Get the list of documents from the database and return the list in an
2920
     * Vector of identifiers.
2921
     *
2922
     * @ returns the array of identifiers
2923
     */
2924
    private Vector<String> getDocumentList() throws SQLException {
2925
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2926
        Vector<String> docList = new Vector<String>();
2927
        PreparedStatement pstmt = null;
2928
        ResultSet rs = null;
2929
        DBConnection conn = null;
2930
        int serialNumber = -1;
2931
        
2932
        try {
2933
            //check out DBConnection
2934
            conn = DBConnectionPool
2935
                    .getDBConnection("MetaCatServlet.getDocumentList");
2936
            serialNumber = conn.getCheckOutSerialNumber();
2937
            pstmt = conn.prepareStatement("SELECT docid, rev"
2938
                    + " FROM xml_documents ");
2939
            pstmt.execute();
2940
            rs = pstmt.getResultSet();
2941
            while (rs.next()) {
2942
                String docid = rs.getString(1);
2943
                String rev = rs.getString(2);
2944
                docList.add(docid + "." + rev);
2945
            }
2946
        } catch (SQLException e) {
2947
            logMetacat.error("MetaCatServlet.getDocumentList - General exception: "
2948
                    + e.getMessage());
2949
            throw e;
2950
        } finally {
2951
            try {
2952
                rs.close();
2953
                pstmt.close();
2954
                
2955
            } catch (SQLException se) {
2956
                logMetacat.error("MetaCatServlet.getDocumentList - General exception: "
2957
                        + se.getMessage());
2958
                throw se;
2959
            } finally {
2960
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2961
            }
2962
        }
2963
        return docList;
2964
    }
2965
    
2966
    /*
2967
     * A method to output setAccess action result
2968
     */
2969
    private void outputResponse(Vector<String> successList, Vector<String> errorList,
2970
            Writer out) {
2971
    	try {
2972
	        boolean error = false;
2973
	        boolean success = false;
2974
	        // Output prolog
2975
	        out.write(PROLOG);
2976
	        // output success message
2977
	        if (successList != null) {
2978
	            for (int i = 0; i < successList.size(); i++) {
2979
	                out.write(SUCCESS);
2980
	                out.write(successList.elementAt(i));
2981
	                out.write(SUCCESSCLOSE);
2982
	                success = true;
2983
	            }
2984
	        }
2985
	        // output error message
2986
	        if (errorList != null) {
2987
	            for (int i = 0; i < errorList.size(); i++) {
2988
	                out.write(ERROR);
2989
	                out.write(errorList.elementAt(i));
2990
	                out.write(ERRORCLOSE);
2991
	                error = true;
2992
	            }
2993
	        }
2994
	        
2995
	        // if no error and no success info, send a error that nothing happened
2996
	        if (!error && !success) {
2997
	            out.write(ERROR);
2998
	            out.write("Nothing happend for setaccess action");
2999
	            out.write(ERRORCLOSE);
3000
	        }
3001
    	} catch (Exception e) {
3002
			logMetacat.error(e.getMessage(), e);
3003
		} 
3004
    }
3005
    
3006
    /*
3007
     * If the given docid only have one seperter, we need
3008
     * append rev for it. The rev come from xml_documents
3009
     */
3010
    private static String appendRev(String docid) throws PropertyNotFoundException, SQLException, McdbDocNotFoundException {
3011
        String newAccNum = null;
3012
        String separator = PropertyService.getProperty("document.accNumSeparator");
3013
        int firstIndex = docid.indexOf(separator);
3014
        int lastIndex = docid.lastIndexOf(separator);
3015
        if (firstIndex == lastIndex) {
3016
            
3017
            //only one seperater
3018
            int rev = DBUtil.getLatestRevisionInDocumentTable(docid);
3019
            if (rev == -1) {
3020
                throw new McdbDocNotFoundException("the requested docid '"
3021
                        + docid+ "' does not exist");
3022
            } else {
3023
                newAccNum = docid+ separator+ rev;
3024
            }
3025
        } else {
3026
            // in other suituation we don't change the docid
3027
            newAccNum = docid;
3028
        }
3029
        //logMetacat.debug("The docid will be read is "+newAccNum);
3030
        return newAccNum;
3031
    }
3032
    
3033
    /**
3034
     * Schedule the sitemap generator to run periodically and update all
3035
     * of the sitemap files for search indexing engines.
3036
     *
3037
     * @param request a servlet request, from which we determine the context
3038
     */
3039
    protected void scheduleSitemapGeneration(HttpServletRequest request) {
3040
        if (!_sitemapScheduled) {
3041
            String directoryName = null;
3042
            String skin = null;
3043
            long sitemapInterval = 0;
3044
            
3045
            try {
3046
                directoryName = SystemUtil.getContextDir() + FileUtil.getFS() + "sitemaps";
3047
                skin = PropertyService.getProperty("application.default-style");
3048
                sitemapInterval = 
3049
                    Integer.parseInt(PropertyService.getProperty("sitemap.interval"));
3050
            } catch (PropertyNotFoundException pnfe) {
3051
                logMetacat.error("MetaCatServlet.scheduleSitemapGeneration - Could not run site map generation because property " 
3052
                        + "could not be found: " + pnfe.getMessage());
3053
            }
3054
            
3055
            File directory = new File(directoryName);
3056
            directory.mkdirs();
3057
            String urlRoot = request.getRequestURL().toString();
3058
            Sitemap smap = new Sitemap(directory, urlRoot, skin);
3059
            long firstDelay = 60*1000;   // 60 seconds delay
3060
            timer.schedule(smap, firstDelay, sitemapInterval);
3061
            _sitemapScheduled = true;
3062
        }
3063
    }
3064

    
3065
    /**
3066
     * @param sitemapScheduled toggle the _sitemapScheduled flag
3067
     */
3068
    public void set_sitemapScheduled(boolean sitemapScheduled) {
3069
        _sitemapScheduled = sitemapScheduled;
3070
    }
3071

    
3072
}
(43-43/65)