Project

General

Profile

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

    
25
package edu.ucsb.nceas.metacat;
26

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

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

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

    
66
import au.com.bytecode.opencsv.CSVWriter;
67

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

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

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

    
110
    private static boolean _sitemapScheduled = false;
111

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

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

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

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

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

    
1093
    /**
1094
     * Create a filename to be used for naming a downloaded document
1095
     * @param docid the identifier of the document to be named
1096
     * @param params the parameters of the request
1097
     * @param doc the DocumentImpl of the document to be named
1098
     * @return String containing a name for the download
1099
     */
1100
    private String generateOutputName(String docid,
1101
            Hashtable<String, String[]> params, DocumentImpl doc) {
1102
        String outputname = null;
1103
        // check for the existence of a metadatadocid parameter,
1104
        // if this is sent, then send a filename which contains both
1105
        // the metadata docid and the data docid, so the link with
1106
        // metadata is explicitly encoded in the filename.
1107
        String metadatadocid = null;
1108
        Vector<String> nameparts = new Vector<String>();
1109

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

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

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

    
2448
        /*
2449
         * response.setContentType("text/xml"); try { out =
2450
         * response.getWriter(); } catch (IOException ioe2) {
2451
         * System.err.println("Fatal Error: couldn't get response output
2452
         * stream.");
2453
         */
2454

    
2455
        if (params.containsKey("docid")) {
2456
            docid = params.get("docid")[0];
2457
        }
2458

    
2459
        if(params.containsKey("qformat")) {
2460
            qformat = params.get("qformat")[0];
2461
        }
2462

    
2463
        // Make sure we have a docid and datafile
2464
        if (docid != null && fileList.containsKey("datafile")) {
2465
            logMetacat.info("MetaCatServlet.handleUploadAction - Uploading data docid: " + docid);
2466
            // Get a reference to the file part of the form
2467
            //FilePart filePart = (FilePart) fileList.get("datafile");
2468
            String fileName = fileList.get("filename");
2469
            logMetacat.info("MetaCatServlet.handleUploadAction - Uploading filename: " + fileName);
2470
            // Check if the right file existed in the uploaded data
2471
            if (fileName != null) {
2472

    
2473
                try {
2474
                    //logMetacat.info("Upload datafile " + docid
2475
                    // +"...", 10);
2476
                    //If document get lock data file grant
2477
                    if (DocumentImpl.getDataFileLockGrant(docid)) {
2478
                        // Save the data file to disk using "docid" as the name
2479
                        String datafilepath = PropertyService.getProperty("application.datafilepath");
2480
                        File dataDirectory = new File(datafilepath);
2481
                        dataDirectory.mkdirs();
2482
                        File newFile = null;
2483
                        //                    File tempFile = null;
2484
                        String tempFileName = fileList.get("name");
2485
                        String newFileName = dataDirectory + File.separator + docid;
2486
                        long size = 0;
2487
                        boolean fileExists = false;
2488

    
2489
                        try {
2490
                            newFile = new File(newFileName);
2491
                            fileExists = newFile.exists();
2492
                            logMetacat.info("MetaCatServlet.handleUploadAction - new file status is: " + fileExists);
2493
                            if ( fileExists == false ) {
2494
                                // copy file to desired output location
2495
                                try {
2496
                                    MetacatUtil.copyFile(tempFileName, newFileName);
2497
                                } catch (IOException ioe) {
2498
                                    logMetacat.error("IO Exception copying file: " +
2499
                                            ioe.getMessage());
2500
                                    ioe.printStackTrace(System.out);
2501
                                }
2502
                                size = newFile.length();
2503
                                if (size == 0) {
2504
                                    throw new IOException("Uploaded file is 0 bytes!");
2505
                                }
2506
                            } // Latent bug here if the file already exists, then the
2507
                              // conditional fails but the document is still registered.
2508
                              // maybe this never happens because we already requested a lock?
2509
                            logMetacat.info("MetaCatServlet.handleUploadAction - Uploading the following to Metacat:" +
2510
                                    fileName + ", " + docid + ", " +
2511
                                    username + ", " + groupnames);
2512
                            //register the file in the database (which generates
2513
                            // an exception
2514
                            //if the docid is not acceptable or other untoward
2515
                            // things happen
2516
                            DocumentImpl.registerDocument(fileName, "BIN", docid,
2517
                                    username, groupnames);
2518
                        } catch (Exception ee) {
2519
                            // If the file did not exist before this method was 
2520
                            // called and an exception is generated while 
2521
                            // creating or registering it, then we want to delete
2522
                            // the file from disk because the operation failed.
2523
                            // However, if the file already existed before the 
2524
                            // method was called, then the exception probably
2525
                            // occurs when registering the document, and so we
2526
                            // want to leave the old file in place.
2527
                            if ( fileExists == false ) {
2528
                                newFile.delete();
2529
                            }
2530
                            
2531
                            logMetacat.info("MetaCatServlet.handleUploadAction - in Exception: fileExists is " + fileExists);
2532
                            logMetacat.error("MetaCatServlet.handleUploadAction - Upload Error: " + ee.getMessage());
2533
                            throw ee;
2534
                        }
2535

    
2536
                        EventLog.getInstance().log(request.getRemoteAddr(),
2537
                                username, docid, "upload");
2538
                        // Force replication this data file
2539
                        // To data file, "insert" and update is same
2540
                        // The fourth parameter is null. Because it is
2541
                        // notification server
2542
                        // and this method is in MetaCatServerlet. It is
2543
                        // original command,
2544
                        // not get force replication info from another metacat
2545
                        ForceReplicationHandler frh = new ForceReplicationHandler(
2546
                                docid, "insert", false, null);
2547
                        logMetacat.debug("MetaCatServlet.handleUploadAction - ForceReplicationHandler created: " + frh.toString());
2548

    
2549
                        // set content type and other response header fields
2550
                        // first
2551
                        output += "<?xml version=\"1.0\"?>";
2552
                        output += "<success>";
2553
                        output += "<docid>" + docid + "</docid>";
2554
                        output += "<size>" + size + "</size>";
2555
                        output += "</success>";
2556
                    }
2557

    
2558
                } catch (Exception e) {
2559

    
2560
                    output += "<?xml version=\"1.0\"?>";
2561
                    output += "<error>";
2562
                    output += e.getMessage();
2563
                    output += "</error>";
2564
                }
2565
            } else {
2566
                // the field did not contain a file
2567
                output += "<?xml version=\"1.0\"?>";
2568
                output += "<error>";
2569
                output += "The uploaded data did not contain a valid file.";
2570
                output += "</error>";
2571
            }
2572
        } else {
2573
            // Error bcse docid missing or file missing
2574
            output += "<?xml version=\"1.0\"?>";
2575
            output += "<error>";
2576
            output += "The uploaded data did not contain a valid docid "
2577
                + "or valid file.";
2578
            output += "</error>";
2579
        }
2580

    
2581
        if (qformat == null || qformat.equals("xml")) {
2582
            response.setContentType("text/xml");
2583
            out.println(output);
2584
        } else {
2585
            try {
2586
                DBTransform trans = new DBTransform();
2587
                response.setContentType("text/html");
2588
                trans.transformXMLDocument(output,
2589
                        "message", "-//W3C//HTML//EN", qformat,
2590
                        out, null, null);
2591
            } catch (Exception e) {
2592

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

    
2976
    /**
2977
     * @param sitemapScheduled toggle the _sitemapScheduled flag
2978
     */
2979
    public void set_sitemapScheduled(boolean sitemapScheduled) {
2980
        _sitemapScheduled = sitemapScheduled;
2981
    }
2982

    
2983
}
(43-43/65)