Project

General

Profile

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

    
25
package edu.ucsb.nceas.metacat;
26

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2518
        /*
2519
         * response.setContentType("text/xml"); try { out =
2520
         * response.getWriter(); } catch (IOException ioe2) {
2521
         * System.err.println("Fatal Error: couldn't get response output
2522
         * stream.");
2523
         */
2524

    
2525
        if (params.containsKey("docid")) {
2526
            docid = params.get("docid")[0];
2527
        }
2528

    
2529
        if(params.containsKey("qformat")) {
2530
            qformat = params.get("qformat")[0];
2531
        }
2532

    
2533
        // Make sure we have a docid and datafile
2534
        if (docid != null && fileList.containsKey("datafile")) {
2535
            logMetacat.info("MetaCatServlet.handleUploadAction - Uploading data docid: " + docid);
2536
            // Get a reference to the file part of the form
2537
            //FilePart filePart = (FilePart) fileList.get("datafile");
2538
            String fileName = fileList.get("filename");
2539
            logMetacat.info("MetaCatServlet.handleUploadAction - Uploading filename: " + fileName);
2540
            // Check if the right file existed in the uploaded data
2541
            if (fileName != null) {
2542

    
2543
                try {
2544
                    //logMetacat.info("Upload datafile " + docid
2545
                    // +"...", 10);
2546
                    //If document get lock data file grant
2547
                    if (DocumentImpl.getDataFileLockGrant(docid)) {
2548
                        // Save the data file to disk using "docid" as the name
2549
                        String datafilepath = PropertyService.getProperty("application.datafilepath");
2550
                        File dataDirectory = new File(datafilepath);
2551
                        dataDirectory.mkdirs();
2552
                        File newFile = null;
2553
                        //                    File tempFile = null;
2554
                        String tempFileName = fileList.get("name");
2555
                        String newFileName = dataDirectory + File.separator + docid;
2556
                        long size = 0;
2557
                        boolean fileExists = false;
2558

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

    
2606
                        EventLog.getInstance().log(request.getRemoteAddr(),
2607
                                username, docid, "upload");
2608
                        // Force replication this data file
2609
                        // To data file, "insert" and update is same
2610
                        // The fourth parameter is null. Because it is
2611
                        // notification server
2612
                        // and this method is in MetaCatServerlet. It is
2613
                        // original command,
2614
                        // not get force replication info from another metacat
2615
                        ForceReplicationHandler frh = new ForceReplicationHandler(
2616
                                docid, "insert", false, null);
2617
                        logMetacat.debug("MetaCatServlet.handleUploadAction - ForceReplicationHandler created: " + frh.toString());
2618

    
2619
                        // set content type and other response header fields
2620
                        // first
2621
                        output += "<?xml version=\"1.0\"?>";
2622
                        output += "<success>";
2623
                        output += "<docid>" + docid + "</docid>";
2624
                        output += "<size>" + size + "</size>";
2625
                        output += "</success>";
2626
                    }
2627

    
2628
                } catch (Exception e) {
2629

    
2630
                    output += "<?xml version=\"1.0\"?>";
2631
                    output += "<error>";
2632
                    output += e.getMessage();
2633
                    output += "</error>";
2634
                }
2635
            } else {
2636
                // the field did not contain a file
2637
                output += "<?xml version=\"1.0\"?>";
2638
                output += "<error>";
2639
                output += "The uploaded data did not contain a valid file.";
2640
                output += "</error>";
2641
            }
2642
        } else {
2643
            // Error bcse docid missing or file missing
2644
            output += "<?xml version=\"1.0\"?>";
2645
            output += "<error>";
2646
            output += "The uploaded data did not contain a valid docid "
2647
                + "or valid file.";
2648
            output += "</error>";
2649
        }
2650

    
2651
        if (qformat == null || qformat.equals("xml")) {
2652
            response.setContentType("text/xml");
2653
            out.println(output);
2654
        } else {
2655
            try {
2656
                DBTransform trans = new DBTransform();
2657
                response.setContentType("text/html");
2658
                trans.transformXMLDocument(output,
2659
                        "message", "-//W3C//HTML//EN", qformat,
2660
                        out, null, null);
2661
            } catch (Exception e) {
2662

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

    
3052
    /**
3053
     * @param sitemapScheduled toggle the _sitemapScheduled flag
3054
     */
3055
    public void set_sitemapScheduled(boolean sitemapScheduled) {
3056
        _sitemapScheduled = sitemapScheduled;
3057
    }
3058

    
3059
}
(43-43/65)