Project

General

Profile

1 5277 jones
/**
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 5211 jones
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 5298 jones
import java.io.OutputStream;
33 5211 jones
import java.io.OutputStreamWriter;
34
import java.io.PrintWriter;
35
import java.io.StringReader;
36 5362 berkley
import java.io.ByteArrayOutputStream;
37 5211 jones
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 5337 berkley
import javax.activation.MimetypesFileTypeMap;
62 5211 jones
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 5298 jones
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
78 5211 jones
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 5277 jones
/**
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 5211 jones
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 5337 berkley
    public MetacatHandler(Timer timer) {
122 5211 jones
    	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 5362 berkley
173 5211 jones
                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 5311 daigle
            e.printStackTrace(System.out);
346 5211 jones
            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
                SessionService.registerSession(id,
360
                        (String) session.getAttribute("username"),
361
                        (String[]) session.getAttribute("groupnames"),
362
                        (String) session.getAttribute("password"),
363
                        (String) session.getAttribute("name"));
364
            } catch (ServiceException se) {
365
                String errorMsg = "MetacatServlet.handleLoginAction - service problem registering session: "
366
                        + se.getMessage();
367
                logMetacat.error("MetaCatServlet.handleLoginAction - " + errorMsg);
368
                out.println(errorMsg);
369 5311 daigle
                se.printStackTrace(System.out);
370 5211 jones
                return;
371
            }
372
        }
373
374
        // format and transform the output
375
        if (qformat.equals("xml")) {
376
            response.setContentType("text/xml");
377
            out.println(sess.getMessage());
378
        } else {
379
            try {
380
                DBTransform trans = new DBTransform();
381
                response.setContentType("text/html");
382
                trans.transformXMLDocument(sess.getMessage(),
383
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
384
                        out, null, null);
385
            } catch (Exception e) {
386
                logMetacat.error("MetaCatServlet.handleLoginAction - General error"
387
                        + e.getMessage());
388 5311 daigle
                e.printStackTrace(System.out);
389 5211 jones
            }
390
        }
391
    }
392
393
    /**
394
     * Handle the logout request. Close the connection.
395
     */
396
    public void handleLogoutAction(PrintWriter out, Hashtable<String, String[]> params,
397
            HttpServletRequest request, HttpServletResponse response) {
398
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
399
        String qformat = "xml";
400
        if(params.get("qformat") != null){
401
            qformat = params.get("qformat")[0];
402
        }
403
404
        // close the connection
405
        HttpSession sess = request.getSession(false);
406
        logMetacat.info("MetaCatServlet.handleLogoutAction - After get session in logout request");
407
        if (sess != null) {
408
            logMetacat.info("MetaCatServlet.handleLogoutAction - The session id " + sess.getId()
409
            + " will be invalidate in logout action");
410
            logMetacat.info("MetaCatServlet.handleLogoutAction - The session contains user "
411
                    + sess.getAttribute("username")
412
                    + " will be invalidate in logout action");
413
            sess.invalidate();
414
            SessionService.unRegisterSession(sess.getId());
415
        }
416
417
        // produce output
418
        StringBuffer output = new StringBuffer();
419
        output.append("<?xml version=\"1.0\"?>");
420
        output.append("<logout>");
421
        output.append("User logged out");
422
        output.append("</logout>");
423
424
        //format and transform the output
425
        if (qformat.equals("xml")) {
426
            response.setContentType("text/xml");
427
            out.println(output.toString());
428
        } else {
429
            try {
430
                DBTransform trans = new DBTransform();
431
                response.setContentType("text/html");
432
                trans.transformXMLDocument(output.toString(),
433
                        "-//NCEAS//login//EN", "-//W3C//HTML//EN", qformat,
434
                        out, null, null);
435
            } catch (Exception e) {
436
                logMetacat.error(
437
                        "MetaCatServlet.handleLogoutAction - General error: "
438
                        + e.getMessage());
439 5311 daigle
                e.printStackTrace(System.out);
440 5211 jones
            }
441
        }
442
    }
443
444
    // END OF LOGIN & LOGOUT SECTION
445
446
    // SQUERY & QUERY SECTION
447
    /**
448
     * Retreive the squery xml, execute it and display it
449
     *
450
     * @param out the output stream to the client
451
     * @param params the Hashtable of parameters that should be included in the
452
     *            squery.
453
     * @param response the response object linked to the client
454
     * @param conn the database connection
455
     */
456
    protected void handleSQuery(PrintWriter out, Hashtable<String, String[]> params,
457
            HttpServletResponse response, String user, String[] groups,
458
            String sessionid) throws PropertyNotFoundException {
459
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
460
        long squeryWarnLimit = Long.parseLong(PropertyService.getProperty("database.squeryTimeWarnLimit"));
461
462
        long startTime = System.currentTimeMillis();
463
        DBQuery queryobj = new DBQuery();
464
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
465
        long outPutTime = System.currentTimeMillis();
466
        long runTime = outPutTime - startTime;
467
468
        if (runTime > squeryWarnLimit) {
469
            logMetacat.warn("MetaCatServlet.handleSQuery - Long running squery.  Total time: " + runTime +
470
                    " ms, squery: " + ((String[])params.get("query"))[0]);
471
        }
472
        logMetacat.debug("MetaCatServlet.handleSQuery - squery: " + ((String[])params.get("query"))[0] +
473
                " ran in " + runTime + " ms");
474
    }
475
476
    /**
477
     * Create the xml query, execute it and display the results.
478
     *
479
     * @param out the output stream to the client
480
     * @param params the Hashtable of parameters that should be included in the
481
     *            squery.
482
     * @param response the response object linked to the client
483
     */
484
    protected void handleQuery(PrintWriter out, Hashtable<String, String[]> params,
485
            HttpServletResponse response, String user, String[] groups,
486
            String sessionid) throws PropertyNotFoundException {
487
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
488
        long queryWarnLimit = Long.parseLong(PropertyService.getProperty("database.queryTimeWarnLimit"));
489
490
        //create the query and run it
491
        String xmlquery = DBQuery.createSQuery(params);
492
        String[] queryArray = new String[1];
493
        queryArray[0] = xmlquery;
494
        params.put("query", queryArray);
495
        long startTime = System.currentTimeMillis();
496
        DBQuery queryobj = new DBQuery();
497
        queryobj.findDocuments(response, out, params, user, groups, sessionid);
498
        long outPutTime = System.currentTimeMillis();
499
        long runTime = outPutTime -startTime;
500
501
        if (runTime > queryWarnLimit) {
502
            logMetacat.warn("MetaCatServlet.handleQuery - Long running squery.  Total time: " + runTime +
503
                    " ms, squery: " + ((String[])params.get("query"))[0]);
504
        }
505
        logMetacat.debug("MetaCatServlet.handleQuery - query: " + ((String[])params.get("query"))[0] +
506
                " ran in " + runTime + " ms");
507
    }
508
509
    // END OF SQUERY & QUERY SECTION
510
511
    //Export section
512
    /**
513
     * Handle the "export" request of data package from Metacat in zip format
514
     *
515
     * @param params the Hashtable of HTTP request parameters
516
     * @param response the HTTP response object linked to the client
517
     * @param user the username sent the request
518
     * @param groups the user's groupnames
519
     */
520
    protected void handleExportAction(Hashtable<String, String[]> params,
521
            HttpServletResponse response,
522
            String user, String[] groups, String passWord) {
523
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
524
        // Output stream
525
        ServletOutputStream out = null;
526
        // Zip output stream
527
        ZipOutputStream zOut = null;
528
        DBQuery queryObj = null;
529
530
        String[] docs = new String[10];
531
        String docId = "";
532
533
        try {
534
            // read the params
535
            if (params.containsKey("docid")) {
536
                docs = params.get("docid");
537
            }
538
            // Create a DBuery to handle export
539
            queryObj = new DBQuery();
540
            // Get the docid
541
            docId = docs[0];
542
            // Make sure the client specify docid
543
            if (docId == null || docId.equals("")) {
544
                response.setContentType("text/xml"); //MIME type
545
                // Get a printwriter
546
                PrintWriter pw = response.getWriter();
547
                // Send back message
548
                pw.println("<?xml version=\"1.0\"?>");
549
                pw.println("<error>");
550
                pw.println("You didn't specify requested docid");
551
                pw.println("</error>");
552
                // Close printwriter
553
                pw.close();
554
                return;
555
            }
556
            // Get output stream
557
            out = response.getOutputStream();
558
            response.setContentType("application/zip"); //MIME type
559
            response.setHeader("Content-Disposition",
560
                    "attachment; filename="
561
                    + docId + ".zip"); // Set the name of the zip file
562
563
            zOut = new ZipOutputStream(out);
564
            zOut = queryObj
565
                    .getZippedPackage(docId, out, user, groups, passWord);
566
            zOut.finish(); //terminate the zip file
567
            zOut.close(); //close the zip stream
568
569
        } catch (Exception e) {
570
            try {
571
                response.setContentType("text/xml"); //MIME type
572
                // Send error message back
573
                if (out != null) {
574
                    PrintWriter pw = new PrintWriter(out);
575
                    pw.println("<?xml version=\"1.0\"?>");
576
                    pw.println("<error>");
577
                    pw.println(e.getMessage());
578
                    pw.println("</error>");
579
                    // Close printwriter
580
                    pw.close();
581
                    // Close output stream
582
                    out.close();
583
                }
584
                // Close zip output stream
585
                if (zOut != null) {
586
                    zOut.close();
587
                }
588
            } catch (IOException ioe) {
589
                logMetacat.error("MetaCatServlet.handleExportAction - Problem with the servlet output: "
590
                        + ioe.getMessage());
591 5311 daigle
                e.printStackTrace(System.out);
592 5211 jones
            }
593
594
            logMetacat.error("MetaCatServlet.handleExportAction - General error: "
595
                    + e.getMessage());
596
            e.printStackTrace(System.out);
597
598
        }
599
600
    }
601
602
    /**
603
     * In eml2 document, the xml can have inline data and data was stripped off
604
     * and store in file system. This action can be used to read inline data
605
     * only
606
     *
607
     * @param params the Hashtable of HTTP request parameters
608
     * @param response the HTTP response object linked to the client
609
     * @param user the username sent the request
610
     * @param groups the user's groupnames
611
     */
612
    protected void handleReadInlineDataAction(Hashtable<String, String[]> params,
613
            HttpServletRequest request, HttpServletResponse response,
614
            String user, String passWord, String[] groups) {
615
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
616
        String[] docs = new String[10];
617
        String inlineDataId = null;
618
        String docId = "";
619
        ServletOutputStream out = null;
620
621
        try {
622
            // read the params
623
            if (params.containsKey("inlinedataid")) {
624
                docs = params.get("inlinedataid");
625
            }
626
            // Get the docid
627
            inlineDataId = docs[0];
628
            // Make sure the client specify docid
629
            if (inlineDataId == null || inlineDataId.equals("")) {
630
                throw new Exception("You didn't specify requested inlinedataid"); }
631
632
            // check for permission
633
            docId =
634
                DocumentUtil.getDocIdWithoutRevFromInlineDataID(inlineDataId);
635
            PermissionController controller = new PermissionController(docId);
636
            // check top level read permission
637
            if (!controller.hasPermission(user, groups,
638
                    AccessControlInterface.READSTRING)) {
639
                throw new Exception("User " + user
640
                        + " doesn't have permission " + " to read document "
641
                        + docId);
642
            } else {
643
                //check data access level
644
                try {
645
                    Hashtable<String,String> unReadableInlineDataList =
646
                            PermissionController.getUnReadableInlineDataIdList(docId,
647
                            user, groups, false);
648
                    String inlineDataIdWithoutRev = DocumentUtil.getInlineDataIdWithoutRev(inlineDataId);
649
                    if (unReadableInlineDataList.containsValue(inlineDataIdWithoutRev)) {
650
                        throw new Exception("User " + user
651
                                + " doesn't have permission " + " to read inlinedata "
652
                                + inlineDataId);
653
654
                    }//if
655
                }//try
656
                catch (Exception e) {
657
                    throw e;
658
                }//catch
659
            }//else
660
661
            // Get output stream
662
            out = response.getOutputStream();
663
            // read the inline data from the file
664
            String inlinePath = PropertyService.getProperty("application.inlinedatafilepath");
665
            File lineData = new File(inlinePath, inlineDataId);
666
            FileInputStream input = new FileInputStream(lineData);
667
            byte[] buffer = new byte[4 * 1024];
668
            int bytes = input.read(buffer);
669
            while (bytes != -1) {
670
                out.write(buffer, 0, bytes);
671
                bytes = input.read(buffer);
672
            }
673
            out.close();
674
675
            EventLog.getInstance().log(request.getRemoteAddr(), user,
676
                    inlineDataId, "readinlinedata");
677
        } catch (Exception e) {
678
            try {
679
                PrintWriter pw = null;
680
                // Send error message back
681
                if (out != null) {
682
                    pw = new PrintWriter(out);
683
                } else {
684
                    pw = response.getWriter();
685
                }
686
                pw.println("<?xml version=\"1.0\"?>");
687
                pw.println("<error>");
688
                pw.println(e.getMessage());
689
                pw.println("</error>");
690
                // Close printwriter
691
                pw.close();
692
                // Close output stream if out is not null
693
                if (out != null) {
694
                    out.close();
695
                }
696
            } catch (IOException ioe) {
697
                logMetacat.error("MetaCatServlet.handleReadInlineDataAction - Problem with the servlet output: "
698
                        + ioe.getMessage());
699 5311 daigle
                e.printStackTrace(System.out);
700 5211 jones
            }
701
            logMetacat.error("MetaCatServlet.handleReadInlineDataAction - General error: "
702
                    + e.getMessage());
703 5311 daigle
            e.printStackTrace(System.out);
704 5211 jones
        }
705
    }
706
707
    /**
708
     * Handle the "read" request of metadata/data files from Metacat or any
709
     * files from Internet; transformed metadata XML document into HTML
710
     * presentation if requested; zip files when more than one were requested.
711
     *
712
     * @param params the Hashtable of HTTP request parameters
713
     * @param request the HTTP request object linked to the client
714
     * @param response the HTTP response object linked to the client
715
     * @param user the username sent the request
716
     * @param groups the user's groupnames
717
     */
718
    public void handleReadAction(Hashtable<String, String[]> params, HttpServletRequest request,
719
            HttpServletResponse response, String user, String passWord,
720
            String[] groups) {
721
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
722
        ServletOutputStream out = null;
723
        ZipOutputStream zout = null;
724
        PrintWriter pw = null;
725
        boolean zip = false;
726
        boolean withInlineData = true;
727
728
        try {
729
            String[] docs = new String[0];
730
            String docid = "";
731
            String qformat = "";
732
733
            // read the params
734
            if (params.containsKey("docid")) {
735
                docs = params.get("docid");
736
            }
737
            if (params.containsKey("qformat")) {
738
                qformat = params.get("qformat")[0];
739
            }
740
            // the param for only metadata (eml)
741
            // we don't support read a eml document without inline data now.
742
            /*if (params.containsKey("inlinedata")) {
743
744
                String inlineData = ((String[]) params.get("inlinedata"))[0];
745
                if (inlineData.equalsIgnoreCase("false")) {
746
                    withInlineData = false;
747
                }
748
            }*/
749
            if ((docs.length > 1) || qformat.equals("zip")) {
750
                zip = true;
751
                out = response.getOutputStream();
752
                response.setContentType("application/zip"); //MIME type
753
                zout = new ZipOutputStream(out);
754
            }
755
            // go through the list of docs to read
756
            for (int i = 0; i < docs.length; i++) {
757
                String providedFileName = null;
758
                if (params.containsKey(docs[i])) {
759
                    providedFileName = params.get(docs[i])[0];
760
                }
761
                try {
762
763
                    URL murl = new URL(docs[i]);
764
                    Hashtable<String,String> murlQueryStr = MetacatUtil.parseQuery(
765
                            murl.getQuery());
766
                    // case docid="http://.../?docid=aaa"
767
                    // or docid="metacat://.../?docid=bbb"
768
                    if (murlQueryStr.containsKey("docid")) {
769
                        // get only docid, eliminate the rest
770
                        docid = murlQueryStr.get("docid");
771
                        if (zip) {
772
                            addDocToZip(request, docid, providedFileName, zout, user, groups);
773
                        } else {
774 5298 jones
                            readFromMetacat(request.getRemoteAddr(), response, response.getOutputStream(), docid, qformat,
775
                                    user, groups, withInlineData, params);
776 5211 jones
                        }
777
778
                        // case docid="http://.../filename"
779
                    } else {
780
                        docid = docs[i];
781
                        if (zip) {
782
                            addDocToZip(request, docid, providedFileName, zout, user, groups);
783
                        } else {
784
                            readFromURLConnection(response, docid);
785
                        }
786
                    }
787
788
                } catch (MalformedURLException mue) {
789
                    docid = docs[i];
790
                    if (zip) {
791
                        addDocToZip(request, docid, providedFileName, zout, user, groups);
792
                    } else {
793 5311 daigle
                    	if (out == null) {
794
                    		out = response.getOutputStream();
795
                    	}
796
                        readFromMetacat(request.getRemoteAddr(), response, out, docid, qformat,
797 5298 jones
                                user, groups, withInlineData, params);
798 5211 jones
                    }
799
                }
800
            }
801
802
            if (zip) {
803
                zout.finish(); //terminate the zip file
804
                zout.close(); //close the zip stream
805
            }
806
807
        } catch (McdbDocNotFoundException notFoundE) {
808
            // To handle doc not found exception
809
            // the docid which didn't be found
810
            String notFoundDocId = notFoundE.getUnfoundDocId();
811
            String notFoundRevision = notFoundE.getUnfoundRevision();
812
            logMetacat.warn("MetaCatServlet.handleReadAction - Missed id: " + notFoundDocId);
813
            logMetacat.warn("MetaCatServlet.handleReadAction - Missed rev: " + notFoundRevision);
814
            try {
815
                // read docid from remote server
816
                readFromRemoteMetaCat(response, notFoundDocId,
817
                        notFoundRevision, user, passWord, out, zip, zout);
818
                // Close zout outputstream
819
                if (zout != null) {
820
                    zout.close();
821
                }
822
                // close output stream
823
                if (out != null) {
824
                    out.close();
825
                }
826
827
            } catch (Exception exc) {
828
                logMetacat.error("MetaCatServlet.handleReadAction - General error: "
829
                        + exc.getMessage());
830 5311 daigle
                exc.printStackTrace(System.out);
831 5211 jones
                try {
832
                    if (out != null) {
833
                        response.setContentType("text/xml");
834
                        // Send back error message by printWriter
835
                        pw = new PrintWriter(out);
836
                        pw.println("<?xml version=\"1.0\"?>");
837
                        pw.println("<error>");
838
                        pw.println(notFoundE.getMessage());
839
                        pw.println("</error>");
840
                        pw.close();
841
                        out.close();
842
843
                    } else {
844
                        response.setContentType("text/xml"); //MIME type
845
                        // Send back error message if out = null
846
                        if (pw == null) {
847
                            // If pw is null, open the respnose
848
                            pw = response.getWriter();
849
                        }
850
                        pw.println("<?xml version=\"1.0\"?>");
851
                        pw.println("<error>");
852
                        pw.println(notFoundE.getMessage());
853
                        pw.println("</error>");
854
                        pw.close();
855
                    }
856
                    // close zout
857
                    if (zout != null) {
858
                        zout.close();
859
                    }
860
                } catch (IOException ie) {
861
                    logMetacat.error("MetaCatServlet.handleReadAction - Problem with the servlet output: "
862
                            + ie.getMessage());
863 5311 daigle
                    ie.printStackTrace(System.out);
864 5211 jones
                }
865
            }
866
        } catch (Exception e) {
867
            try {
868
869
                if (out != null) {
870
                    response.setContentType("text/xml"); //MIME type
871
                    pw = new PrintWriter(out);
872
                    pw.println("<?xml version=\"1.0\"?>");
873
                    pw.println("<error>");
874
                    pw.println(e.getMessage());
875
                    pw.println("</error>");
876
                    pw.close();
877
                    out.close();
878
                } else {
879
                    response.setContentType("text/xml"); //MIME type
880
                    // Send back error message if out = null
881
                    if (pw == null) {
882
                        pw = response.getWriter();
883
                    }
884
                    pw.println("<?xml version=\"1.0\"?>");
885
                    pw.println("<error>");
886
                    pw.println(e.getMessage());
887
                    pw.println("</error>");
888
                    pw.close();
889
890
                }
891
                // Close zip output stream
892
                if (zout != null) {
893
                    zout.close();
894
                }
895
896
            } catch (Exception e2) {
897
                logMetacat.error("MetaCatServlet.handleReadAction - Problem with the servlet output: "
898
                        + e2.getMessage());
899
                e2.printStackTrace(System.out);
900
901
            }
902
903
            logMetacat.error("MetaCatServlet.handleReadAction - General error: "
904
                    + e.getMessage());
905 5311 daigle
            e.printStackTrace(System.out);
906 5211 jones
        }
907
    }
908
909 5362 berkley
    /**
910
     *
911
     * @return
912
     */
913
    public void query(String metacatUrl, PrintWriter out, Hashtable<String, String[]>params,
914
            String username, String[] groups, String sessionid)
915
      throws Exception
916
    {
917
        handleQuery(out, params, null, username, groups, sessionid);
918
    }
919
920
    /**
921
     * set the access permissions on the document specified
922
     */
923
    public void setAccess(String metacatUrl, String username, String docid, String principal,
924
            String permission, String permissionType, String permissionOrder)
925
      throws Exception
926
    {
927
        Hashtable<String,String[]> params = new Hashtable();
928
        params.put("principal", new String[] {principal});
929
        params.put("permission", new String[] {permission});
930
        params.put("permType", new String[] {permissionType});
931
        params.put("permOrder", new String[] {permissionOrder});
932
        params.put("docid", new String[]{docid});
933
934
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
935
        PrintWriter out = new PrintWriter(baos);
936
        handleSetAccessAction(out, params, username, null, null);
937
        System.out.println("Set acces to " + permission + " for document " + docid);
938
    }
939
940 5211 jones
    /** read metadata or data from Metacat
941 5298 jones
     * @throws PropertyNotFoundException
942
     * @throws ParseLSIDException
943
     * @throws InsufficientKarmaException
944 5211 jones
     */
945 5298 jones
    public void readFromMetacat(String ipAddress,
946
            HttpServletResponse response, OutputStream out, String docid, String qformat,
947
            String user, String[] groups, boolean withInlineData,
948
            Hashtable<String, String[]> params) throws ClassNotFoundException,
949
            IOException, SQLException, McdbException, PropertyNotFoundException,
950
            ParseLSIDException, InsufficientKarmaException {
951 5211 jones
952 5298 jones
        Logger logMetacat = Logger.getLogger(MetacatHandler.class);
953 5211 jones
        try {
954
955
            if (docid.startsWith("urn:")) {
956
                docid = LSIDUtil.getDocId(docid, true);
957
            }
958
959
            // here is hack for handle docid=john.10(in order to tell mike.jim.10.1
960
            // mike.jim.10, we require to provide entire docid with rev). But
961
            // some old client they only provide docid without rev, so we need
962
            // to handle this suituation. First we will check how many
963
            // seperator here, if only one, we will append the rev in xml_documents
964
            // to the id.
965
            docid = appendRev(docid);
966
967
            DocumentImpl doc = new DocumentImpl(docid);
968
969
            //check the permission for read
970
            if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
971 5298 jones
                InsufficientKarmaException e = new InsufficientKarmaException("User " + user
972 5211 jones
                        + " does not have permission"
973
                        + " to read the document with the docid " + docid);
974
                throw e;
975
            }
976
977
            if (doc.getRootNodeID() == 0) {
978 5298 jones
                // this is data file, so find the path on disk for the file
979 5211 jones
                String filepath = PropertyService.getProperty("application.datafilepath");
980
                if (!filepath.endsWith("/")) {
981
                    filepath += "/";
982
                }
983
                String filename = filepath + docid;
984
                FileInputStream fin = null;
985
                fin = new FileInputStream(filename);
986
987 5298 jones
                if (response != null) {
988
                    // MIME type
989 5337 berkley
                    //String contentType = servletContext.getMimeType(filename);
990
                    String contentType = (new MimetypesFileTypeMap()).getContentType(filename);
991 5298 jones
                    if (contentType == null) {
992
                        ContentTypeProvider provider = new ContentTypeProvider(
993
                                docid);
994
                        contentType = provider.getContentType();
995
                        logMetacat.info("MetaCatServlet.readFromMetacat - Final contenttype is: "
996
                                + contentType);
997
                    }
998
                    response.setContentType(contentType);
999 5211 jones
1000 5298 jones
                    // Set the output filename on the response
1001
                    String outputname = generateOutputName(docid, params, doc);
1002
                    response.setHeader("Content-Disposition",
1003
                            "attachment; filename=\"" + outputname + "\"");
1004 5211 jones
                }
1005
1006 5298 jones
                // Write the data to the output stream
1007 5211 jones
                try {
1008
                    byte[] buf = new byte[4 * 1024]; // 4K buffer
1009
                    int b = fin.read(buf);
1010
                    while (b != -1) {
1011
                        out.write(buf, 0, b);
1012
                        b = fin.read(buf);
1013
                    }
1014
                } finally {
1015
                    if (fin != null) fin.close();
1016
                }
1017
1018
            } else {
1019
                // this is metadata doc
1020
                if (qformat.equals("xml") || qformat.equals("")) {
1021
                    // if equals "", that means no qformat is specified. hence
1022
                    // by default the document should be returned in xml format
1023
                    // set content type first
1024
1025 5298 jones
                    if (response != null) {
1026
                        response.setContentType("text/xml"); //MIME type
1027
                        response.setHeader("Content-Disposition",
1028
                                "attachment; filename=" + docid + ".xml");
1029
                    }
1030
1031 5211 jones
                    // Try to get the metadata file from disk. If it isn't
1032
                    // found, create it from the db and write it to disk then.
1033
                    try {
1034 5298 jones
                        PrintWriter pw = new PrintWriter(out);
1035
                        doc.toXml(pw, user, groups, withInlineData);
1036
                    } catch (McdbException e) {
1037 5211 jones
                        // any exceptions in reading the xml from disc, and we go back to the
1038
                        // old way of creating the xml directly.
1039
                        logMetacat.error("MetaCatServlet.readFromMetacat - could not read from document file " + docid
1040
                                + ": " + e.getMessage());
1041 5311 daigle
                        e.printStackTrace(System.out);
1042 5298 jones
                        PrintWriter pw = new PrintWriter(out);
1043
                        doc.toXmlFromDb(pw, user, groups, withInlineData);
1044 5211 jones
                    }
1045
                } else {
1046
                    // TODO MCD, this should read from disk as well?
1047
                    //*** This is a metadata doc, to be returned in a skin/custom format.
1048
                    //*** Add param to indicate if public has read access or not.
1049 5322 berkley
                    logMetacat.debug("User: \n" + user);
1050 5211 jones
                    if (!user.equals("public")) {
1051
                        if (DocumentImpl.hasReadPermission("public", null, docid))
1052
                            params.put("publicRead", new String[] {"true"});
1053
                        else
1054
                            params.put("publicRead", new String[] {"false"});
1055
                    }
1056
1057 5298 jones
                    if (response != null) {
1058
                        response.setContentType("text/html"); //MIME type
1059
                    }
1060 5211 jones
1061 5298 jones
                    PrintWriter pw = new PrintWriter(out);
1062
1063 5211 jones
                    // Look up the document type
1064
                    String doctype = doc.getDoctype();
1065
                    // Transform the document to the new doctype
1066
                    DBTransform dbt = new DBTransform();
1067
                    dbt.transformXMLDocument(doc.toString(user, groups,
1068
                            withInlineData), doctype, "-//W3C//HTML//EN",
1069 5298 jones
                            qformat, pw, params, null);
1070 5211 jones
                }
1071
1072
            }
1073 5298 jones
            EventLog.getInstance().log(ipAddress, user, docid, "read");
1074
        } catch (PropertyNotFoundException except) {
1075 5211 jones
            throw except;
1076
        }
1077
    }
1078 5298 jones
1079
    /**
1080
     * Create a filename to be used for naming a downloaded document
1081
     * @param docid the identifier of the document to be named
1082
     * @param params the parameters of the request
1083
     * @param doc the DocumentImpl of the document to be named
1084
     * @return String containing a name for the download
1085
     */
1086
    private String generateOutputName(String docid,
1087
            Hashtable<String, String[]> params, DocumentImpl doc) {
1088
        String outputname = null;
1089
        // check for the existence of a metadatadocid parameter,
1090
        // if this is sent, then send a filename which contains both
1091
        // the metadata docid and the data docid, so the link with
1092
        // metadata is explicitly encoded in the filename.
1093
        String metadatadocid = null;
1094
        Vector<String> nameparts = new Vector<String>();
1095
1096
        if(params.containsKey("metadatadocid")) {
1097
            metadatadocid = params.get("metadatadocid")[0];
1098
        }
1099
        if (metadatadocid != null && !metadatadocid.equals("")) {
1100
            nameparts.add(metadatadocid);
1101
        }
1102
        // we'll always have the docid, include it in the name
1103
        String doctype = doc.getDoctype();
1104
        // TODO: fix this to lookup the associated FGDC metadata document,
1105
        // and grab the doctype tag for it.  These should be set to something
1106
        // consistent, not 'metadata' as it stands...
1107
        //if (!doctype.equals("metadata")) {
1108
        //    nameparts.add(docid);
1109
        //}
1110
        nameparts.add(docid);
1111
        // Set the name of the data file to the entity name plus docid,
1112
        // or if that is unavailable, use the docid alone
1113
        String docname = doc.getDocname();
1114
        if (docname != null && !docname.equals("")) {
1115
            nameparts.add(docname);
1116
        }
1117
        // combine the name elements with a dash, using a 'join' equivalent
1118
        String delimiter = "-";
1119
        Iterator<String> iter = nameparts.iterator();
1120
        StringBuffer buffer = new StringBuffer(iter.next());
1121
        while (iter.hasNext()) buffer.append(delimiter).append(iter.next());
1122
        outputname = buffer.toString();
1123
        return outputname;
1124
    }
1125 5211 jones
1126
    /**
1127
     * read data from URLConnection
1128
     */
1129
    private void readFromURLConnection(HttpServletResponse response,
1130
            String docid) throws IOException, MalformedURLException {
1131
        ServletOutputStream out = response.getOutputStream();
1132 5337 berkley
        //String contentType = servletContext.getMimeType(docid); //MIME type
1133
        String contentType = (new MimetypesFileTypeMap()).getContentType(docid);
1134 5211 jones
        if (contentType == null) {
1135
            if (docid.endsWith(".xml")) {
1136
                contentType = "text/xml";
1137
            } else if (docid.endsWith(".css")) {
1138
                contentType = "text/css";
1139
            } else if (docid.endsWith(".dtd")) {
1140
                contentType = "text/plain";
1141
            } else if (docid.endsWith(".xsd")) {
1142
                contentType = "text/xml";
1143
            } else if (docid.endsWith("/")) {
1144
                contentType = "text/html";
1145
            } else {
1146
                File f = new File(docid);
1147
                if (f.isDirectory()) {
1148
                    contentType = "text/html";
1149
                } else {
1150
                    contentType = "application/octet-stream";
1151
                }
1152
            }
1153
        }
1154
        response.setContentType(contentType);
1155
        // if we decide to use "application/octet-stream" for all data returns
1156
        // response.setContentType("application/octet-stream");
1157
1158
        // this is http url
1159
        URL url = new URL(docid);
1160
        BufferedInputStream bis = null;
1161
        try {
1162
            bis = new BufferedInputStream(url.openStream());
1163
            byte[] buf = new byte[4 * 1024]; // 4K buffer
1164
            int b = bis.read(buf);
1165
            while (b != -1) {
1166
                out.write(buf, 0, b);
1167
                b = bis.read(buf);
1168
            }
1169
        } finally {
1170
            if (bis != null) bis.close();
1171
        }
1172
1173
    }
1174
1175
    /**
1176
     * read file/doc and write to ZipOutputStream
1177
     *
1178
     * @param docid
1179
     * @param zout
1180
     * @param user
1181
     * @param groups
1182
     * @throws ClassNotFoundException
1183
     * @throws IOException
1184
     * @throws SQLException
1185
     * @throws McdbException
1186
     * @throws Exception
1187
     */
1188
    private void addDocToZip(HttpServletRequest request, String docid, String providedFileName,
1189
            ZipOutputStream zout, String user, String[] groups) throws
1190
            ClassNotFoundException, IOException, SQLException, McdbException,
1191
            Exception {
1192
        byte[] bytestring = null;
1193
        ZipEntry zentry = null;
1194
1195
        try {
1196
            URL url = new URL(docid);
1197
1198
            // this http url; read from URLConnection; add to zip
1199
            //use provided file name if we have one
1200
            if (providedFileName != null && providedFileName.length() > 1) {
1201
                zentry = new ZipEntry(providedFileName);
1202
            }
1203
            else {
1204
                zentry = new ZipEntry(docid);
1205
            }
1206
            zout.putNextEntry(zentry);
1207
            BufferedInputStream bis = null;
1208
            try {
1209
                bis = new BufferedInputStream(url.openStream());
1210
                byte[] buf = new byte[4 * 1024]; // 4K buffer
1211
                int b = bis.read(buf);
1212
                while (b != -1) {
1213
                    zout.write(buf, 0, b);
1214
                    b = bis.read(buf);
1215
                }
1216
            } finally {
1217
                if (bis != null) bis.close();
1218
            }
1219
            zout.closeEntry();
1220
1221
        } catch (MalformedURLException mue) {
1222
1223
            // this is metacat doc (data file or metadata doc)
1224
            try {
1225
                DocumentImpl doc = new DocumentImpl(docid);
1226
1227
                //check the permission for read
1228
                if (!DocumentImpl.hasReadPermission(user, groups, docid)) {
1229
                    Exception e = new Exception("User " + user
1230
                            + " does not have "
1231
                            + "permission to read the document with the docid "
1232
                            + docid);
1233
                    throw e;
1234
                }
1235
1236
                if (doc.getRootNodeID() == 0) {
1237
                    // this is data file; add file to zip
1238
                    String filepath = PropertyService.getProperty("application.datafilepath");
1239
                    if (!filepath.endsWith("/")) {
1240
                        filepath += "/";
1241
                    }
1242
                    String filename = filepath + docid;
1243
                    FileInputStream fin = null;
1244
                    fin = new FileInputStream(filename);
1245
                    try {
1246
                        //use provided file name if we have one
1247
                        if (providedFileName != null && providedFileName.length() > 1) {
1248
                            zentry = new ZipEntry(providedFileName);
1249
                        }
1250
                        else {
1251
                            zentry = new ZipEntry(docid);
1252
                        }
1253
                        zout.putNextEntry(zentry);
1254
                        byte[] buf = new byte[4 * 1024]; // 4K buffer
1255
                        int b = fin.read(buf);
1256
                        while (b != -1) {
1257
                            zout.write(buf, 0, b);
1258
                            b = fin.read(buf);
1259
                        }
1260
                    } finally {
1261
                        if (fin != null) fin.close();
1262
                    }
1263
                    zout.closeEntry();
1264
1265
                } else {
1266
                    // this is metadata doc; add doc to zip
1267
                    bytestring = doc.toString().getBytes();
1268
                    //use provided file name if given
1269
                    if (providedFileName != null && providedFileName.length() > 1) {
1270
                        zentry = new ZipEntry(providedFileName);
1271
                    }
1272
                    else {
1273
                        zentry = new ZipEntry(docid + ".xml");
1274
                    }
1275
                    zentry.setSize(bytestring.length);
1276
                    zout.putNextEntry(zentry);
1277
                    zout.write(bytestring, 0, bytestring.length);
1278
                    zout.closeEntry();
1279
                }
1280
                EventLog.getInstance().log(request.getRemoteAddr(), user,
1281
                        docid, "read");
1282
            } catch (Exception except) {
1283
                throw except;
1284
            }
1285
        }
1286
    }
1287
1288
    /**
1289
     * If metacat couldn't find a data file or document locally, it will read
1290
     * this docid from its home server. This is for the replication feature
1291
     */
1292
    private void readFromRemoteMetaCat(HttpServletResponse response,
1293
            String docid, String rev, String user, String password,
1294
            ServletOutputStream out, boolean zip, ZipOutputStream zout)
1295
            throws Exception {
1296
        // Create a object of RemoteDocument, "" is for zipEntryPath
1297
        RemoteDocument remoteDoc = new RemoteDocument(docid, rev, user,
1298
                password, "");
1299
        String docType = remoteDoc.getDocType();
1300
        // Only read data file
1301
        if (docType.equals("BIN")) {
1302
            // If it is zip format
1303
            if (zip) {
1304
                remoteDoc.readDocumentFromRemoteServerByZip(zout);
1305
            } else {
1306
                if (out == null) {
1307
                    out = response.getOutputStream();
1308
                }
1309
                response.setContentType("application/octet-stream");
1310
                remoteDoc.readDocumentFromRemoteServer(out);
1311
            }
1312
        } else {
1313
            throw new Exception("Docid: " + docid + "." + rev
1314
                    + " couldn't find");
1315
        }
1316
    }
1317
1318
    /**
1319
     * Handle the database putdocument request and write an XML document to the
1320
     * database connection
1321
     */
1322 5337 berkley
    public String handleInsertOrUpdateAction(String ipAddress,
1323 5211 jones
            HttpServletResponse response, PrintWriter out, Hashtable<String, String[]> params,
1324
            String user, String[] groups) {
1325
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1326
        DBConnection dbConn = null;
1327
        int serialNumber = -1;
1328
        String output = "";
1329
        String qformat = null;
1330
        if(params.containsKey("qformat"))
1331
        {
1332
          qformat = params.get("qformat")[0];
1333
        }
1334
1335
        if(params.get("docid") == null){
1336 5337 berkley
            String msg = "<?xml version=\"1.0\"?>" +
1337
                "<error>" +
1338
                "Docid not specified" +
1339
                "</error>";
1340
            if(out != null)
1341
            {
1342
                out.println(msg);
1343
                logMetacat.error("MetaCatServlet.handleInsertOrUpdateAction - Docid not specified");
1344
            }
1345
            return msg;
1346 5211 jones
        }
1347
1348
        try {
1349
            if (!AuthUtil.canInsertOrUpdate(user, groups)) {
1350 5337 berkley
                String msg = "<?xml version=\"1.0\"?>" +
1351
                "<error>" +
1352
                "User '" + user + "' not allowed to insert and update" +
1353
                "</error>";
1354
                if(out != null)
1355
                {
1356
                  out.println(msg);
1357
                }
1358
1359 5211 jones
                logMetacat.error("MetaCatServlet.handleInsertOrUpdateAction - User '" + user + "' not allowed to insert and update");
1360 5337 berkley
                return msg;
1361 5211 jones
            }
1362
        } catch (MetacatUtilException ue) {
1363
            logMetacat.error("MetaCatServlet.handleInsertOrUpdateAction - Could not determine if user could insert or update: "
1364
                    + ue.getMessage());
1365 5311 daigle
            ue.printStackTrace(System.out);
1366 5325 jones
            // TODO: This is a bug, as it allows one to bypass the access check -- need to throw an exception
1367 5211 jones
        }
1368
1369
        try {
1370
            // Get the document indicated
1371
            logMetacat.debug("MetaCatServlet.handleInsertOrUpdateAction - params: " + params.toString());
1372
1373
            String[] doctext = params.get("doctext");
1374
            String pub = null;
1375
            if (params.containsKey("public")) {
1376
                pub = params.get("public")[0];
1377
            }
1378
1379
            StringReader dtd = null;
1380
            if (params.containsKey("dtdtext")) {
1381
                String[] dtdtext = params.get("dtdtext");
1382
                try {
1383
                    if (!dtdtext[0].equals("")) {
1384
                        dtd = new StringReader(dtdtext[0]);
1385
                    }
1386
                } catch (NullPointerException npe) {
1387
                }
1388
            }
1389
1390
            if(doctext == null){
1391 5337 berkley
                String msg = "<?xml version=\"1.0\"?>" +
1392
                "<error>" +
1393
                "Document text not submitted." +
1394
                "</error>";
1395
                if(out != null)
1396
                {
1397
                  out.println(msg);
1398
                }
1399
1400 5325 jones
                // TODO: this should really throw an exception
1401 5337 berkley
                return msg;
1402 5211 jones
            }
1403
1404
            logMetacat.debug("MetaCatServlet.handleInsertOrUpdateAction - the xml document in metacat servlet (before parsing):\n" + doctext[0]);
1405
            StringReader xmlReader = new StringReader(doctext[0]);
1406
            boolean validate = false;
1407
            DocumentImplWrapper documentWrapper = null;
1408
            try {
1409
                // look inside XML Document for <!DOCTYPE ... PUBLIC/SYSTEM ...
1410
                // >
1411
                // in order to decide whether to use validation parser
1412
                validate = needDTDValidation(xmlReader);
1413
                if (validate) {
1414
                    // set a dtd base validation parser
1415
                    String rule = DocumentImpl.DTD;
1416
                    documentWrapper = new DocumentImplWrapper(rule, validate);
1417
                } else {
1418
1419
                    String namespace = XMLSchemaService.findDocumentNamespace(xmlReader);
1420
1421
                    if (namespace != null) {
1422
                        if (namespace.compareTo(DocumentImpl.EML2_0_0NAMESPACE) == 0
1423
                                || namespace.compareTo(
1424
                                DocumentImpl.EML2_0_1NAMESPACE) == 0) {
1425
                            // set eml2 base     validation parser
1426
                            String rule = DocumentImpl.EML200;
1427
                            // using emlparser to check id validation
1428
                            @SuppressWarnings("unused")
1429
                            EMLParser parser = new EMLParser(doctext[0]);
1430
                            documentWrapper = new DocumentImplWrapper(rule, true);
1431
                        } else if (namespace.compareTo(
1432
                                DocumentImpl.EML2_1_0NAMESPACE) == 0) {
1433
                            // set eml2 base validation parser
1434
                            String rule = DocumentImpl.EML210;
1435
                            // using emlparser to check id validation
1436
                            @SuppressWarnings("unused")
1437
                            EMLParser parser = new EMLParser(doctext[0]);
1438
                            documentWrapper = new DocumentImplWrapper(rule, true);
1439
                        } else {
1440
                            // set schema base validation parser
1441
                            String rule = DocumentImpl.SCHEMA;
1442
                            documentWrapper = new DocumentImplWrapper(rule, true);
1443
                        }
1444
                    } else {
1445
                        documentWrapper = new DocumentImplWrapper("", false);
1446
                    }
1447
                }
1448
1449
                String[] action = params.get("action");
1450
                String[] docid = params.get("docid");
1451
                String newdocid = null;
1452
1453
                String doAction = null;
1454
                if (action[0].equals("insert") || action[0].equals("insertmultipart")) {
1455
                    doAction = "INSERT";
1456
                } else if (action[0].equals("update")) {
1457
                    doAction = "UPDATE";
1458
                }
1459
1460
                try {
1461
                    // get a connection from the pool
1462
                    dbConn = DBConnectionPool
1463
                            .getDBConnection("MetaCatServlet.handleInsertOrUpdateAction");
1464
                    serialNumber = dbConn.getCheckOutSerialNumber();
1465
1466
                    // write the document to the database and disk
1467
                    String accNumber = docid[0];
1468
                    logMetacat.debug("MetaCatServlet.handleInsertOrUpdateAction - " + doAction + " "
1469
                            + accNumber + "...");
1470
                    if (accNumber == null || accNumber.equals("")) {
1471
                        logMetacat.warn("MetaCatServlet.handleInsertOrUpdateAction - writing with null acnumber");
1472
                        newdocid = documentWrapper.write(dbConn, doctext[0], pub, dtd,
1473
                                doAction, null, user, groups);
1474 5319 jones
                        EventLog.getInstance().log(ipAddress, user, "", action[0]);
1475
                    } else {
1476
                        newdocid = documentWrapper.write(dbConn, doctext[0], pub, dtd,
1477
                                doAction, accNumber, user, groups);
1478
1479
                        EventLog.getInstance().log(ipAddress, user, accNumber, action[0]);
1480
                    }
1481 5211 jones
                } finally {
1482
                    // Return db connection
1483
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1484
                }
1485
1486
                // set content type and other response header fields first
1487
                //response.setContentType("text/xml");
1488
                output += "<?xml version=\"1.0\"?>";
1489
                output += "<success>";
1490
                output += "<docid>" + newdocid + "</docid>";
1491
                output += "</success>";
1492
1493
            } catch (NullPointerException npe) {
1494
                //response.setContentType("text/xml");
1495
                output += "<?xml version=\"1.0\"?>";
1496
                output += "<error>";
1497
                output += npe.getMessage();
1498
                output += "</error>";
1499
                logMetacat.warn("MetaCatServlet.handleInsertOrUpdateAction - Null pointer error when writing eml document to the database: " + npe.getMessage());
1500
                npe.printStackTrace();
1501
            }
1502
        } catch (Exception e) {
1503
            //response.setContentType("text/xml");
1504
            output += "<?xml version=\"1.0\"?>";
1505
            output += "<error>";
1506
            output += e.getMessage();
1507
            output += "</error>";
1508
            logMetacat.warn("MetaCatServlet.handleInsertOrUpdateAction - General error when writing eml document to the database: " + e.getMessage());
1509
            e.printStackTrace();
1510
        }
1511
1512
        if (qformat == null || qformat.equals("xml")) {
1513 5337 berkley
            if(response != null)
1514
            {
1515
              response.setContentType("text/xml");
1516
              out.println(output);
1517
            }
1518
            return output;
1519 5211 jones
        } else {
1520
            try {
1521
                DBTransform trans = new DBTransform();
1522
                response.setContentType("text/html");
1523
                trans.transformXMLDocument(output,
1524
                        "message", "-//W3C//HTML//EN", qformat,
1525
                        out, null, null);
1526
            } catch (Exception e) {
1527
1528
                logMetacat.error("MetaCatServlet.handleInsertOrUpdateAction - General error: "
1529
                        + e.getMessage());
1530 5311 daigle
                e.printStackTrace(System.out);
1531 5211 jones
            }
1532
        }
1533 5337 berkley
        return null;
1534 5211 jones
    }
1535
1536
    /**
1537
     * Parse XML Document to look for <!DOCTYPE ... PUBLIC/SYSTEM ... > in
1538
     * order to decide whether to use validation parser
1539
     */
1540
    private static boolean needDTDValidation(StringReader xmlreader)
1541
    throws IOException {
1542
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1543
        StringBuffer cbuff = new StringBuffer();
1544
        java.util.Stack<String> st = new java.util.Stack<String>();
1545
        boolean validate = false;
1546
        boolean commented = false;
1547
        int c;
1548
        int inx;
1549
1550
        // read from the stream until find the keywords
1551
        while ((st.empty() || st.size() < 4) && ((c = xmlreader.read()) != -1)) {
1552
            cbuff.append((char) c);
1553
1554
            if ((inx = cbuff.toString().indexOf("<!--")) != -1) {
1555
                commented = true;
1556
            }
1557
1558
            // "<!DOCTYPE" keyword is found; put it in the stack
1559
            if ((inx = cbuff.toString().indexOf("<!DOCTYPE")) != -1) {
1560
                cbuff = new StringBuffer();
1561
                st.push("<!DOCTYPE");
1562
            }
1563
            // "PUBLIC" keyword is found; put it in the stack
1564
            if ((inx = cbuff.toString().indexOf("PUBLIC")) != -1) {
1565
                cbuff = new StringBuffer();
1566
                st.push("PUBLIC");
1567
            }
1568
            // "SYSTEM" keyword is found; put it in the stack
1569
            if ((inx = cbuff.toString().indexOf("SYSTEM")) != -1) {
1570
                cbuff = new StringBuffer();
1571
                st.push("SYSTEM");
1572
            }
1573
            // ">" character is found; put it in the stack
1574
            // ">" is found twice: fisrt from <?xml ...?>
1575
            // and second from <!DOCTYPE ... >
1576
            if ((inx = cbuff.toString().indexOf(">")) != -1) {
1577
                cbuff = new StringBuffer();
1578
                st.push(">");
1579
            }
1580
        }
1581
1582
        // close the stream
1583
        xmlreader.reset();
1584
1585
        // check the stack whether it contains the keywords:
1586
        // "<!DOCTYPE", "PUBLIC" or "SYSTEM", and ">" in this order
1587
        if (st.size() == 4) {
1588
            if ((st.pop()).equals(">")
1589
            && ((st.peek()).equals("PUBLIC") | (st.pop()).equals("SYSTEM"))
1590
                    && (st.pop()).equals("<!DOCTYPE")) {
1591
                validate = true && !commented;
1592
            }
1593
        }
1594
1595
        logMetacat.info("MetaCatServlet.needDTDValidation - Validation for dtd is " + validate);
1596
        return validate;
1597
    }
1598
1599
    // END OF INSERT/UPDATE SECTION
1600
1601
    /**
1602
     * Handle the database delete request and delete an XML document from the
1603
     * database connection
1604
     */
1605
    public void handleDeleteAction(PrintWriter out, Hashtable<String, String[]> params,
1606
            HttpServletRequest request, HttpServletResponse response,
1607
            String user, String[] groups) {
1608
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1609
        String[] docid = params.get("docid");
1610
1611
        if(docid == null){
1612
            response.setContentType("text/xml");
1613
            out.println("<?xml version=\"1.0\"?>");
1614
            out.println("<error>");
1615
            out.println("Docid not specified.");
1616
            out.println("</error>");
1617
            logMetacat.error("MetaCatServlet.handleDeleteAction - Docid not specified for the document to be deleted.");
1618
        } else {
1619
1620
            // delete the document from the database
1621
            try {
1622
1623
                try {
1624
                    // null means notify server is null
1625
                    DocumentImpl.delete(docid[0], user, groups, null);
1626
                    EventLog.getInstance().log(request.getRemoteAddr(),
1627
                            user, docid[0], "delete");
1628
                    response.setContentType("text/xml");
1629
                    out.println("<?xml version=\"1.0\"?>");
1630
                    out.println("<success>");
1631
                    out.println("Document deleted.");
1632
                    out.println("</success>");
1633
                    logMetacat.info("MetaCatServlet.handleDeleteAction - Document deleted.");
1634
1635
                    // Delete from spatial cache if runningSpatialOption
1636
                    if ( PropertyService.getProperty("spatial.runSpatialOption").equals("true") ) {
1637
                        SpatialHarvester sh = new SpatialHarvester();
1638
                        sh.addToDeleteQue( DocumentUtil.getSmartDocId( docid[0] ) );
1639
                        sh.destroy();
1640
                    }
1641
1642
                } catch (AccessionNumberException ane) {
1643
                    response.setContentType("text/xml");
1644
                    out.println("<?xml version=\"1.0\"?>");
1645
                    out.println("<error>");
1646
                    //out.println("Error deleting document!!!");
1647
                    out.println(ane.getMessage());
1648
                    out.println("</error>");
1649
                    logMetacat.error("MetaCatServlet.handleDeleteAction - Document could not be deleted: "
1650
                            + ane.getMessage());
1651 5311 daigle
                    ane.printStackTrace(System.out);
1652 5211 jones
                }
1653
            } catch (Exception e) {
1654
                response.setContentType("text/xml");
1655
                out.println("<?xml version=\"1.0\"?>");
1656
                out.println("<error>");
1657
                out.println(e.getMessage());
1658
                out.println("</error>");
1659
                logMetacat.error("MetaCatServlet.handleDeleteAction - Document could not be deleted: "
1660
                        + e.getMessage());
1661 5311 daigle
                e.printStackTrace(System.out);
1662 5211 jones
            }
1663
        }
1664
    }
1665
1666
    /**
1667
     * Handle the validation request and return the results to the requestor
1668
     */
1669
    protected void handleValidateAction(PrintWriter out, Hashtable<String, String[]> params) {
1670
1671
        // Get the document indicated
1672
        String valtext = null;
1673
        DBConnection dbConn = null;
1674
        int serialNumber = -1;
1675
1676
        try {
1677
            valtext = params.get("valtext")[0];
1678
        } catch (Exception nullpe) {
1679
1680
            String docid = null;
1681
            try {
1682
                // Find the document id number
1683
                docid = params.get("docid")[0];
1684
1685
                // Get the document indicated from the db
1686
                DocumentImpl xmldoc = new DocumentImpl(docid);
1687
                valtext = xmldoc.toString();
1688
1689
            } catch (NullPointerException npe) {
1690
1691
                out.println("<error>Error getting document ID: " + docid
1692
                        + "</error>");
1693
                //if ( conn != null ) { util.returnConnection(conn); }
1694
                return;
1695
            } catch (Exception e) {
1696
1697
                out.println(e.getMessage());
1698
            }
1699
        }
1700
1701
        try {
1702
            // get a connection from the pool
1703
            dbConn = DBConnectionPool
1704
                    .getDBConnection("MetaCatServlet.handleValidateAction");
1705
            serialNumber = dbConn.getCheckOutSerialNumber();
1706
            DBValidate valobj = new DBValidate(dbConn);
1707
//            boolean valid = valobj.validateString(valtext);
1708
1709
            // set content type and other response header fields first
1710
1711
            out.println(valobj.returnErrors());
1712
1713
        } catch (NullPointerException npe2) {
1714
            // set content type and other response header fields first
1715
1716
            out.println("<error>Error validating document.</error>");
1717
        } catch (Exception e) {
1718
1719
            out.println(e.getMessage());
1720
        } finally {
1721
            // Return db connection
1722
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1723
        }
1724
    }
1725
1726
    /**
1727
     * Handle "getrevsionanddoctype" action Given a docid, return it's current
1728
     * revision and doctype from data base The output is String look like
1729
     * "rev;doctype"
1730
     */
1731
    protected void handleGetRevisionAndDocTypeAction(PrintWriter out,
1732
            Hashtable<String, String[]> params) {
1733
        // To store doc parameter
1734
        String[] docs = new String[10];
1735
        // Store a single doc id
1736
        String givenDocId = null;
1737
        // Get docid from parameters
1738
        if (params.containsKey("docid")) {
1739
            docs = params.get("docid");
1740
        }
1741
        // Get first docid form string array
1742
        givenDocId = docs[0];
1743
1744
        try {
1745
            // Make sure there is a docid
1746
            if (givenDocId == null || givenDocId.equals("")) { throw new Exception(
1747
                    "User didn't specify docid!"); }//if
1748
1749
            // Create a DBUtil object
1750
            DBUtil dbutil = new DBUtil();
1751
            // Get a rev and doctype
1752
            String revAndDocType = dbutil
1753
                    .getCurrentRevisionAndDocTypeForGivenDocument(givenDocId);
1754
            out.println(revAndDocType);
1755
1756
        } catch (Exception e) {
1757
            // Handle exception
1758
            out.println("<?xml version=\"1.0\"?>");
1759
            out.println("<error>");
1760
            out.println(e.getMessage());
1761
            out.println("</error>");
1762
        }
1763
1764
    }
1765
1766
    /**
1767
     * Handle "getaccesscontrol" action. Read Access Control List from db
1768
     * connection in XML format
1769
     */
1770
    protected void handleGetAccessControlAction(PrintWriter out,
1771
            Hashtable<String,String[]> params, HttpServletResponse response, String username,
1772
            String[] groupnames) {
1773
1774
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1775
1776
        String docid = params.get("docid")[0];
1777
        if (docid.startsWith("urn:")) {
1778
            try {
1779
                String actualDocId = LSIDUtil.getDocId(docid, false);
1780
                docid = actualDocId;
1781
            } catch (ParseLSIDException ple) {
1782
                logMetacat.error("MetaCatServlet.handleGetAccessControlAction - MetaCatServlet.handleGetAccessControlAction - " +
1783 5311 daigle
                        "could not parse lsid: " + docid + " : " + ple.getMessage());
1784
                ple.printStackTrace(System.out);
1785 5211 jones
            }
1786
        }
1787
1788
        String qformat = "xml";
1789
        if (params.get("qformat") != null) {
1790
            qformat = (params.get("qformat"))[0];
1791
        }
1792
1793
        try {
1794
            AccessControlForSingleFile acfsf = new AccessControlForSingleFile(docid);
1795
            String acltext = acfsf.getACL(username, groupnames);
1796
            if (qformat.equals("xml")) {
1797
                response.setContentType("text/xml");
1798
                out.println(acltext);
1799
            } else {
1800
                DBTransform trans = new DBTransform();
1801
                response.setContentType("text/html");
1802
                trans.transformXMLDocument(acltext,"-//NCEAS//getaccesscontrol//EN",
1803
                    "-//W3C//HTML//EN", qformat, out, params, null);
1804
            }
1805
        } catch (Exception e) {
1806
            out.println("<?xml version=\"1.0\"?>");
1807
            out.println("<error>");
1808
            out.println(e.getMessage());
1809
            out.println("</error>");
1810
        }
1811
//        finally {
1812
//            // Retrun db connection to pool
1813
//            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1814
//        }
1815
    }
1816
1817
    /**
1818
     * Handle the "getprincipals" action. Read all principals from
1819
     * authentication scheme in XML format
1820
     */
1821
    protected void handleGetPrincipalsAction(PrintWriter out, String user,
1822
            String password) {
1823
        try {
1824
            AuthSession auth = new AuthSession();
1825
            String principals = auth.getPrincipals(user, password);
1826
            out.println(principals);
1827
1828
        } catch (Exception e) {
1829
            out.println("<?xml version=\"1.0\"?>");
1830
            out.println("<error>");
1831
            out.println(e.getMessage());
1832
            out.println("</error>");
1833
        }
1834
    }
1835
1836
    /**
1837
     * Handle "getdoctypes" action. Read all doctypes from db connection in XML
1838
     * format
1839
     */
1840
    protected void handleGetDoctypesAction(PrintWriter out, Hashtable<String, String[]> params,
1841
            HttpServletResponse response) {
1842
        try {
1843
            DBUtil dbutil = new DBUtil();
1844
            String doctypes = dbutil.readDoctypes();
1845
            out.println(doctypes);
1846
        } catch (Exception e) {
1847
            out.println("<?xml version=\"1.0\"?>");
1848
            out.println("<error>");
1849
            out.println(e.getMessage());
1850
            out.println("</error>");
1851
        }
1852
    }
1853
1854
    /**
1855
     * Handle the "getdtdschema" action. Read DTD or Schema file for a given
1856
     * doctype from Metacat catalog system
1857
     */
1858
    protected void handleGetDTDSchemaAction(PrintWriter out, Hashtable<String, String[]> params,
1859
            HttpServletResponse response) {
1860
1861
        String doctype = null;
1862
        String[] doctypeArr = params.get("doctype");
1863
1864
        // get only the first doctype specified in the list of doctypes
1865
        // it could be done for all doctypes in that list
1866
        if (doctypeArr != null) {
1867
            doctype = params.get("doctype")[0];
1868
        }
1869
1870
        try {
1871
            DBUtil dbutil = new DBUtil();
1872
            String dtdschema = dbutil.readDTDSchema(doctype);
1873
            out.println(dtdschema);
1874
1875
        } catch (Exception e) {
1876
            out.println("<?xml version=\"1.0\"?>");
1877
            out.println("<error>");
1878
            out.println(e.getMessage());
1879
            out.println("</error>");
1880
        }
1881
1882
    }
1883
1884
    /**
1885
     * Check if the document is registered in either the xml_documents or xml_revisions table
1886
     * @param out the writer to write the xml results to
1887
     * @param params request parameters
1888
     * @param response the http servlet response
1889
     */
1890
    public void handleIdIsRegisteredAction(PrintWriter out, Hashtable<String, String[]> params,
1891
            HttpServletResponse response) {
1892
        String id = null;
1893
        boolean exists = false;
1894
        if(params.get("docid") != null) {
1895
            id = params.get("docid")[0];
1896
        }
1897
1898
        try {
1899
            DBUtil dbutil = new DBUtil();
1900
            exists = dbutil.idExists(id);
1901
        } catch (Exception e) {
1902
            out.println("<?xml version=\"1.0\"?>");
1903
            out.println("<error>");
1904
            out.println(e.getMessage());
1905
            out.println("</error>");
1906
        }
1907
1908
        out.println("<?xml version=\"1.0\"?>");
1909
        out.println("<isRegistered>");
1910
        out.println("<docid>" + id + "</docid>");
1911
        out.println("<exists>" + exists + "</exists>");
1912
        out.println("</isRegistered>");
1913
    }
1914
1915
    /**
1916
     * Handle the "getalldocids" action. return a list of all docids registered
1917
     * in the system
1918
     */
1919
    public void handleGetAllDocidsAction(PrintWriter out, Hashtable<String, String[]> params,
1920
            HttpServletResponse response) {
1921
        String scope = null;
1922
        if(params.get("scope") != null) {
1923
            scope = params.get("scope")[0];
1924
        }
1925
1926
        try {
1927
            DBUtil dbutil = new DBUtil();
1928
            Vector<String> docids = dbutil.getAllDocids(scope);
1929
            out.println("<?xml version=\"1.0\"?>");
1930
            out.println("<idList>");
1931
            out.println("  <scope>" + scope + "</scope>");
1932
            for(int i=0; i<docids.size(); i++) {
1933
                String docid = docids.elementAt(i);
1934
                out.println("  <docid>" + docid + "</docid>");
1935
            }
1936
            out.println("</idList>");
1937
1938
        } catch (Exception e) {
1939
            out.println("<?xml version=\"1.0\"?>");
1940
            out.println("<error>");
1941
            out.println(e.getMessage());
1942
            out.println("</error>");
1943
        }
1944
    }
1945
1946
    /**
1947
     * Handle the "getlastdocid" action. Get the latest docid with rev number
1948
     * from db connection in XML format
1949
     */
1950
    public void handleGetMaxDocidAction(PrintWriter out, Hashtable<String, String[]> params,
1951
            HttpServletResponse response) {
1952
1953
        String scope = params.get("scope")[0];
1954
        if (scope == null) {
1955
            scope = params.get("username")[0];
1956
        }
1957
1958
        try {
1959
1960
            DBUtil dbutil = new DBUtil();
1961
            String lastDocid = dbutil.getMaxDocid(scope);
1962
            out.println("<?xml version=\"1.0\"?>");
1963
            out.println("<lastDocid>");
1964
            out.println("  <scope>" + scope + "</scope>");
1965
            out.println("  <docid>" + lastDocid + "</docid>");
1966
            out.println("</lastDocid>");
1967
1968
        } catch (Exception e) {
1969
            out.println("<?xml version=\"1.0\"?>");
1970
            out.println("<error>");
1971
            out.println(e.getMessage());
1972
            out.println("</error>");
1973
        }
1974
    }
1975
1976
    /**
1977
     * Print a report from the event log based on filter parameters passed in
1978
     * from the web.
1979
     *
1980
     * @param params the parameters from the web request
1981
     * @param request the http request object for getting request details
1982
     * @param response the http response object for writing output
1983
     */
1984
    protected void handleGetLogAction(Hashtable<String, String[]> params, HttpServletRequest request,
1985
            HttpServletResponse response, String username, String[] groups) {
1986
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
1987
        try {
1988
            response.setContentType("text/xml");
1989
            PrintWriter out = response.getWriter();
1990
1991
            // Check that the user is authenticated as an administrator account
1992
            if (!AuthUtil.isAdministrator(username, groups)) {
1993
                out.print("<error>");
1994
                out.print("The user \"" + username +
1995
                        "\" is not authorized for this action.");
1996
                out.print("</error>");
1997
                return;
1998
            }
1999
2000
            // Get all of the parameters in the correct formats
2001
            String[] ipAddress = params.get("ipaddress");
2002
            String[] principal = params.get("principal");
2003
            String[] docid = params.get("docid");
2004
            String[] event = params.get("event");
2005
            String[] startArray = params.get("start");
2006
            String[] endArray = params.get("end");
2007
            String start = null;
2008
            String end = null;
2009
            if (startArray != null) {
2010
                start = startArray[0];
2011
            }
2012
            if (endArray != null) {
2013
                end = endArray[0];
2014
            }
2015
            Timestamp startDate = null;
2016
            Timestamp endDate = null;
2017
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
2018
            try {
2019
                if (start != null) {
2020
                    startDate = new Timestamp((format.parse(start)).getTime());
2021
                }
2022
                if (end != null) {
2023
                    endDate = new Timestamp((format.parse(end)).getTime());
2024
                }
2025
            } catch (ParseException e) {
2026
                logMetacat.error("MetaCatServlet.handleGetLogAction - Failed to created Timestamp from input.");
2027 5311 daigle
                e.printStackTrace(System.out);
2028 5211 jones
            }
2029
2030
            // Request the report by passing the filter parameters
2031
            out.println(EventLog.getInstance().getReport(ipAddress, principal,
2032
                    docid, event, startDate, endDate));
2033
            out.close();
2034
        } catch (IOException e) {
2035
            logMetacat.error("MetaCatServlet.handleGetLogAction - Could not open http response for writing: "
2036
                    + e.getMessage());
2037 5311 daigle
            e.printStackTrace(System.out);
2038 5211 jones
        } catch (MetacatUtilException ue) {
2039
            logMetacat.error("MetaCatServlet.handleGetLogAction - Could not determine if user is administrator: "
2040
                    + ue.getMessage());
2041 5311 daigle
            ue.printStackTrace(System.out);
2042 5211 jones
        }
2043
    }
2044
2045
    /**
2046
     * Rebuild the index for one or more documents. If the docid parameter is
2047
     * provided, rebuild for just that one document or list of documents. If
2048
     * not, then rebuild the index for all documents in the xml_documents table.
2049
     *
2050
     * @param params
2051
     *            the parameters from the web request
2052
     * @param request
2053
     *            the http request object for getting request details
2054
     * @param response
2055
     *            the http response object for writing output
2056
     * @param username
2057
     *            the username of the authenticated user
2058
     */
2059
    protected void handleBuildIndexAction(Hashtable<String, String[]> params,
2060
            HttpServletRequest request, HttpServletResponse response,
2061
            String username, String[] groups) {
2062
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2063
2064
        // Get all of the parameters in the correct formats
2065
        String[] docid = params.get("docid");
2066
2067
        // Rebuild the indices for appropriate documents
2068
        try {
2069
            response.setContentType("text/xml");
2070
            PrintWriter out = response.getWriter();
2071
2072
            // Check that the user is authenticated as an administrator account
2073
            if (!AuthUtil.isAdministrator(username, groups)) {
2074
                out.print("<error>");
2075
                out.print("The user \"" + username +
2076
                        "\" is not authorized for this action.");
2077
                out.print("</error>");
2078
                return;
2079
            }
2080
2081
            // Process the documents
2082
            out.println("<success>");
2083
            if (docid == null || docid.length == 0) {
2084
                // Process all of the documents
2085
                try {
2086
                    Vector<String> documents = getDocumentList();
2087
                    Iterator<String> it = documents.iterator();
2088
                    while (it.hasNext()) {
2089
                        String id = it.next();
2090
                        buildDocumentIndex(id, out);
2091
                    }
2092
                } catch (SQLException se) {
2093
                    out.print("<error>");
2094
                    out.print(se.getMessage());
2095
                    out.println("</error>");
2096
                }
2097
            } else {
2098
                // Only process the requested documents
2099
                for (int i = 0; i < docid.length; i++) {
2100
                    buildDocumentIndex(docid[i], out);
2101
                }
2102
            }
2103
            out.println("</success>");
2104
            out.close();
2105
        } catch (IOException e) {
2106
            logMetacat.error("MetaCatServlet.handleBuildIndexAction - Could not open http response for writing: "
2107
                    + e.getMessage());
2108 5311 daigle
            e.printStackTrace(System.out);
2109 5211 jones
        } catch (MetacatUtilException ue) {
2110
            logMetacat.error("MetaCatServlet.handleBuildIndexAction - Could not determine if user is administrator: "
2111
                    + ue.getMessage());
2112 5311 daigle
            ue.printStackTrace(System.out);
2113 5211 jones
        }
2114
    }
2115
2116
    /**
2117
     * Build the index for one document by reading the document and
2118
     * calling its buildIndex() method.
2119
     *
2120
     * @param docid the document (with revision) to rebuild
2121
     * @param out the PrintWriter to which output is printed
2122
     */
2123
    private void buildDocumentIndex(String docid, PrintWriter out) {
2124
        try {
2125
            DocumentImpl doc = new DocumentImpl(docid, false);
2126
            doc.buildIndex();
2127
            out.print("<docid>" + docid);
2128
            out.println("</docid>");
2129
        } catch (McdbException me) {
2130
            out.print("<error>");
2131
            out.print(me.getMessage());
2132
            out.println("</error>");
2133
        }
2134
    }
2135
2136
    /**
2137
     * Handle documents passed to metacat that are encoded using the
2138
     * "multipart/form-data" mime type. This is typically used for uploading
2139
     * data files which may be binary and large.
2140
     */
2141
    protected void handleMultipartForm(HttpServletRequest request,
2142
            HttpServletResponse response) {
2143
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2144
        PrintWriter out = null;
2145
        String action = null;
2146
2147
        // Parse the multipart form, and save the parameters in a Hashtable and
2148
        // save the FileParts in a hashtable
2149
2150
        Hashtable<String,String[]> params = new Hashtable<String,String[]>();
2151
        Hashtable<String,String> fileList = new Hashtable<String,String>();
2152
        int sizeLimit = 1000;
2153
        try {
2154
            sizeLimit =
2155
                (new Integer(PropertyService.getProperty("replication.datafilesizelimit"))).intValue();
2156
        } catch (PropertyNotFoundException pnfe) {
2157
            logMetacat.error("MetaCatServlet.handleMultipartForm - Could not determine data file size limit.  Using 1000. "
2158
                    + pnfe.getMessage());
2159 5311 daigle
            pnfe.printStackTrace(System.out);
2160 5211 jones
        }
2161
        logMetacat.debug("MetaCatServlet.handleMultipartForm - The size limit of uploaded data files is: " + sizeLimit);
2162
2163
        try {
2164
            MultipartParser mp = new MultipartParser(request,
2165
                    sizeLimit * 1024 * 1024);
2166
            Part part;
2167
2168
            while ((part = mp.readNextPart()) != null) {
2169
                String name = part.getName();
2170
2171
                if (part.isParam()) {
2172
                    // it's a parameter part
2173
                    ParamPart paramPart = (ParamPart) part;
2174
                    String[] values = new String[1];
2175
                    values[0] = paramPart.getStringValue();
2176
                    params.put(name, values);
2177
                    if (name.equals("action")) {
2178
                        action = values[0];
2179
                    }
2180
                } else if (part.isFile()) {
2181
                    // it's a file part
2182
                    FilePart filePart = (FilePart) part;
2183
                    String fileName = filePart.getFileName();
2184
                    String fileTempLocation;
2185
2186
                    // the filePart will be clobbered on the next loop, save to disk
2187
                    fileTempLocation = MetacatUtil.writeTempUploadFile(filePart, fileName);
2188
                    fileList.put(name, fileTempLocation);
2189
                    fileList.put("filename", fileName);
2190
                    fileList.put("name", fileTempLocation);
2191
                } else {
2192
                    logMetacat.info("MetaCatServlet.handleMultipartForm - Upload name '" + name + "' was empty.");
2193
                }
2194
            }
2195
        } catch (IOException ioe) {
2196
            try {
2197
                out = response.getWriter();
2198
            } catch (IOException ioe2) {
2199
                logMetacat.fatal("MetaCatServlet.handleMultipartForm - Fatal Error: couldn't get response output stream.");
2200
            }
2201
            out.println("<?xml version=\"1.0\"?>");
2202
            out.println("<error>");
2203
            out.println("Error: problem reading multipart data: " + ioe.getMessage());
2204
            out.println("</error>");
2205
            out.close();
2206
            return;
2207
        }
2208
2209
        // Get the session information
2210
        String username = null;
2211
        String password = null;
2212
        String[] groupnames = null;
2213
        String sess_id = null;
2214
2215
        // be aware of session expiration on every request
2216
        HttpSession sess = request.getSession(true);
2217
        if (sess.isNew()) {
2218
            // session expired or has not been stored b/w user requests
2219
            username = "public";
2220
            sess.setAttribute("username", username);
2221
        } else {
2222
            username = (String) sess.getAttribute("username");
2223
            password = (String) sess.getAttribute("password");
2224
            groupnames = (String[]) sess.getAttribute("groupnames");
2225
            try {
2226
                sess_id = (String) sess.getId();
2227
            } catch (IllegalStateException ise) {
2228
                System.out
2229
                        .println("error in  handleMultipartForm: this shouldn't "
2230
                        + "happen: the session should be valid: "
2231
                        + ise.getMessage());
2232
            }
2233
        }
2234
2235
        // Get the out stream
2236
        try {
2237
            out = response.getWriter();
2238
        } catch (IOException ioe2) {
2239
            logMetacat.error("MetaCatServlet.handleMultipartForm - Fatal Error: couldn't get response "
2240
                    + "output stream.");
2241 5311 daigle
            ioe2.printStackTrace(System.out);
2242 5211 jones
        }
2243
2244
        if (action.equals("upload")) {
2245
            if (username != null && !username.equals("public")) {
2246
                handleUploadAction(request, out, params, fileList, username,
2247
                        groupnames, response);
2248
            } else {
2249
                out.println("<?xml version=\"1.0\"?>");
2250
                out.println("<error>");
2251
                out.println("Permission denied for " + action);
2252
                out.println("</error>");
2253
            }
2254
        } else if(action.equals("insertmultipart")) {
2255
          if (username != null && !username.equals("public")) {
2256
            logMetacat.debug("MetaCatServlet.handleMultipartForm - handling multipart insert");
2257
              handleInsertMultipartAction(request, response,
2258
                            out, params, fileList, username, groupnames);
2259
          } else {
2260
              out.println("<?xml version=\"1.0\"?>");
2261
              out.println("<error>");
2262
              out.println("Permission denied for " + action);
2263
              out.println("</error>");
2264
          }
2265
        } else {
2266
            /*
2267
             * try { out = response.getWriter(); } catch (IOException ioe2) {
2268
             * System.err.println("Fatal Error: couldn't get response output
2269
             * stream.");
2270
             */
2271
            out.println("<?xml version=\"1.0\"?>");
2272
            out.println("<error>");
2273
            out.println("Error: action not registered.  Please report this error.");
2274
            out.println("</error>");
2275
        }
2276
        out.close();
2277
    }
2278
2279
    /**
2280
     * Handle the upload action by saving the attached file to disk and
2281
     * registering it in the Metacat db
2282
     */
2283
    private void handleInsertMultipartAction(HttpServletRequest request,
2284
            HttpServletResponse response,
2285
            PrintWriter out, Hashtable<String,String[]> params, Hashtable<String,String> fileList,
2286
            String username, String[] groupnames)
2287
    {
2288
      Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2289
      String action = null;
2290
      String docid = null;
2291
      String qformat = null;
2292
      String output = "";
2293
2294
      /*
2295
       * response.setContentType("text/xml"); try { out =
2296
       * response.getWriter(); } catch (IOException ioe2) {
2297
       * System.err.println("Fatal Error: couldn't get response output
2298
       * stream.");
2299
       */
2300
2301
      if (params.containsKey("docid"))
2302
      {
2303
          docid = params.get("docid")[0];
2304
      }
2305
2306
      if(params.containsKey("qformat"))
2307
      {
2308
          qformat = params.get("qformat")[0];
2309
      }
2310
2311
      // Make sure we have a docid and datafile
2312
      if (docid != null && fileList.containsKey("datafile"))
2313
      {
2314
        logMetacat.info("MetaCatServlet.handleInsertMultipartAction - Uploading data docid: " + docid);
2315
        // Get a reference to the file part of the form
2316
        //FilePart filePart = (FilePart) fileList.get("datafile");
2317
        String fileName = fileList.get("filename");
2318
        logMetacat.debug("MetaCatServlet.handleInsertMultipartAction - Uploading filename: " + fileName);
2319
        // Check if the right file existed in the uploaded data
2320
        if (fileName != null)
2321
        {
2322
2323
          try
2324
          {
2325
              //logMetacat.info("Upload datafile " + docid
2326
              // +"...", 10);
2327
              //If document get lock data file grant
2328
            if (DocumentImpl.getDataFileLockGrant(docid))
2329
            {
2330
              // Save the data file to disk using "docid" as the name
2331
              String datafilepath = PropertyService.getProperty("application.datafilepath");
2332
              File dataDirectory = new File(datafilepath);
2333
              dataDirectory.mkdirs();
2334
              File newFile = null;
2335
    //          File tempFile = null;
2336
              String tempFileName = fileList.get("name");
2337
              String newFileName = dataDirectory + File.separator + docid;
2338
              long size = 0;
2339
              boolean fileExists = false;
2340
2341
              try
2342
              {
2343
                newFile = new File(newFileName);
2344
                fileExists = newFile.exists();
2345
                logMetacat.info("MetaCatServlet.handleInsertMultipartAction - new file status is: " + fileExists);
2346
                if(fileExists)
2347
                {
2348
                  newFile.delete();
2349
                  newFile.createNewFile();
2350
                  fileExists = false;
2351
                }
2352
2353
                if ( fileExists == false )
2354
                {
2355
                    // copy file to desired output location
2356
                    try
2357
                    {
2358
                        MetacatUtil.copyFile(tempFileName, newFileName);
2359
                    }
2360
                    catch (IOException ioe)
2361
                    {
2362
                        logMetacat.error("MetaCatServlet.handleInsertMultipartAction - IO Exception copying file: " +
2363
                                ioe.getMessage());
2364 5311 daigle
                        ioe.printStackTrace(System.out);
2365 5211 jones
                    }
2366
                    size = newFile.length();
2367
                    if (size == 0)
2368
                    {
2369
                        throw new IOException("MetaCatServlet.handleInsertMultipartAction - Uploaded file is 0 bytes!");
2370
                    }
2371
                }
2372
                logMetacat.info("MetaCatServlet.handleInsertMultipartAction - Uploading the following to Metacat:" +
2373
                        fileName + ", " + docid + ", " +
2374
                        username + ", " + groupnames);
2375
                FileReader fr = new FileReader(newFile);
2376
2377
                char[] c = new char[1024];
2378
                int numread = fr.read(c, 0, 1024);
2379
                StringBuffer sb = new StringBuffer();
2380
                while(numread != -1)
2381
                {
2382
                  sb.append(c, 0, numread);
2383
                  numread = fr.read(c, 0, 1024);
2384
                }
2385
2386
                Enumeration<String> keys = params.keys();
2387
                while(keys.hasMoreElements())
2388
                { //convert the params to arrays
2389
                  String key = keys.nextElement();
2390
                  String[] paramValue = params.get(key);
2391
                  String[] s = new String[1];
2392
                  s[0] = paramValue[0];
2393
                  params.put(key, s);
2394
                }
2395
                //add the doctext to the params
2396
                String doctext = sb.toString();
2397
                String[] doctextArr = new String[1];
2398
                doctextArr[0] = doctext;
2399
                params.put("doctext", doctextArr);
2400
                //call the insert routine
2401 5319 jones
                handleInsertOrUpdateAction(request.getRemoteAddr(), response, out,
2402 5211 jones
                          params, username, groupnames);
2403
              }
2404
              catch(Exception e)
2405
              {
2406
                throw e;
2407
              }
2408
            }
2409
          }
2410
          catch(Exception e)
2411
          {
2412
              logMetacat.error("MetaCatServlet.handleInsertMultipartAction - error uploading text file via multipart: " + e.getMessage());
2413 5311 daigle
              e.printStackTrace(System.out);;
2414 5211 jones
          }
2415
        }
2416
      }
2417
    }
2418
2419
    /**
2420
     * Handle the upload action by saving the attached file to disk and
2421
     * registering it in the Metacat db
2422
     */
2423
    private void handleUploadAction(HttpServletRequest request,
2424
            PrintWriter out, Hashtable<String, String[]> params, Hashtable<String,String> fileList,
2425
            String username, String[] groupnames, HttpServletResponse response) {
2426
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2427
        //PrintWriter out = null;
2428
        //Connection conn = null;
2429 5319 jones
        //        String action = null;
2430 5211 jones
        String docid = null;
2431
        String qformat = null;
2432
        String output = "";
2433 5319 jones
2434 5211 jones
        /*
2435
         * response.setContentType("text/xml"); try { out =
2436
         * response.getWriter(); } catch (IOException ioe2) {
2437
         * System.err.println("Fatal Error: couldn't get response output
2438
         * stream.");
2439
         */
2440 5319 jones
2441 5211 jones
        if (params.containsKey("docid")) {
2442
            docid = params.get("docid")[0];
2443
        }
2444 5319 jones
2445 5211 jones
        if(params.containsKey("qformat")) {
2446
            qformat = params.get("qformat")[0];
2447
        }
2448 5319 jones
2449 5211 jones
        // Make sure we have a docid and datafile
2450
        if (docid != null && fileList.containsKey("datafile")) {
2451
            logMetacat.info("MetaCatServlet.handleUploadAction - Uploading data docid: " + docid);
2452
            // Get a reference to the file part of the form
2453
            //FilePart filePart = (FilePart) fileList.get("datafile");
2454
            String fileName = fileList.get("filename");
2455
            logMetacat.info("MetaCatServlet.handleUploadAction - Uploading filename: " + fileName);
2456
            // Check if the right file existed in the uploaded data
2457
            if (fileName != null) {
2458 5319 jones
2459 5211 jones
                try {
2460
                    //logMetacat.info("Upload datafile " + docid
2461
                    // +"...", 10);
2462
                    //If document get lock data file grant
2463
                    if (DocumentImpl.getDataFileLockGrant(docid)) {
2464
                        // Save the data file to disk using "docid" as the name
2465
                        String datafilepath = PropertyService.getProperty("application.datafilepath");
2466
                        File dataDirectory = new File(datafilepath);
2467
                        dataDirectory.mkdirs();
2468
                        File newFile = null;
2469 5319 jones
                        //                    File tempFile = null;
2470 5211 jones
                        String tempFileName = fileList.get("name");
2471
                        String newFileName = dataDirectory + File.separator + docid;
2472
                        long size = 0;
2473
                        boolean fileExists = false;
2474 5319 jones
2475 5211 jones
                        try {
2476
                            newFile = new File(newFileName);
2477
                            fileExists = newFile.exists();
2478
                            logMetacat.info("MetaCatServlet.handleUploadAction - new file status is: " + fileExists);
2479
                            if ( fileExists == false ) {
2480
                                // copy file to desired output location
2481
                                try {
2482
                                    MetacatUtil.copyFile(tempFileName, newFileName);
2483
                                } catch (IOException ioe) {
2484
                                    logMetacat.error("IO Exception copying file: " +
2485
                                            ioe.getMessage());
2486 5311 daigle
                                    ioe.printStackTrace(System.out);
2487 5211 jones
                                }
2488
                                size = newFile.length();
2489
                                if (size == 0) {
2490
                                    throw new IOException("Uploaded file is 0 bytes!");
2491
                                }
2492 5319 jones
                            } // Latent bug here if the file already exists, then the
2493
                              // conditional fails but the document is still registered.
2494
                              // maybe this never happens because we already requested a lock?
2495 5211 jones
                            logMetacat.info("MetaCatServlet.handleUploadAction - Uploading the following to Metacat:" +
2496
                                    fileName + ", " + docid + ", " +
2497
                                    username + ", " + groupnames);
2498
                            //register the file in the database (which generates
2499
                            // an exception
2500
                            //if the docid is not acceptable or other untoward
2501
                            // things happen
2502
                            DocumentImpl.registerDocument(fileName, "BIN", docid,
2503
                                    username, groupnames);
2504
                        } catch (Exception ee) {
2505 5319 jones
                            // If the file did not exist before this method was
2506
                            // called and an exception is generated while
2507
                            // creating or registering it, then we want to delete
2508
                            // the file from disk because the operation failed.
2509
                            // However, if the file already existed before the
2510
                            // method was called, then the exception probably
2511
                            // occurs when registering the document, and so we
2512
                            // want to leave the old file in place.
2513 5211 jones
                            if ( fileExists == false ) {
2514
                                newFile.delete();
2515
                            }
2516 5319 jones
2517 5211 jones
                            logMetacat.info("MetaCatServlet.handleUploadAction - in Exception: fileExists is " + fileExists);
2518
                            logMetacat.error("MetaCatServlet.handleUploadAction - Upload Error: " + ee.getMessage());
2519
                            throw ee;
2520
                        }
2521 5319 jones
2522 5211 jones
                        EventLog.getInstance().log(request.getRemoteAddr(),
2523
                                username, docid, "upload");
2524
                        // Force replication this data file
2525
                        // To data file, "insert" and update is same
2526
                        // The fourth parameter is null. Because it is
2527
                        // notification server
2528
                        // and this method is in MetaCatServerlet. It is
2529
                        // original command,
2530
                        // not get force replication info from another metacat
2531
                        ForceReplicationHandler frh = new ForceReplicationHandler(
2532
                                docid, "insert", false, null);
2533
                        logMetacat.debug("MetaCatServlet.handleUploadAction - ForceReplicationHandler created: " + frh.toString());
2534 5319 jones
2535 5211 jones
                        // set content type and other response header fields
2536
                        // first
2537
                        output += "<?xml version=\"1.0\"?>";
2538
                        output += "<success>";
2539
                        output += "<docid>" + docid + "</docid>";
2540
                        output += "<size>" + size + "</size>";
2541
                        output += "</success>";
2542
                    }
2543 5319 jones
2544 5211 jones
                } catch (Exception e) {
2545 5319 jones
2546 5211 jones
                    output += "<?xml version=\"1.0\"?>";
2547
                    output += "<error>";
2548
                    output += e.getMessage();
2549
                    output += "</error>";
2550
                }
2551
            } else {
2552
                // the field did not contain a file
2553
                output += "<?xml version=\"1.0\"?>";
2554
                output += "<error>";
2555
                output += "The uploaded data did not contain a valid file.";
2556
                output += "</error>";
2557
            }
2558
        } else {
2559
            // Error bcse docid missing or file missing
2560
            output += "<?xml version=\"1.0\"?>";
2561
            output += "<error>";
2562
            output += "The uploaded data did not contain a valid docid "
2563 5319 jones
                + "or valid file.";
2564 5211 jones
            output += "</error>";
2565
        }
2566 5319 jones
2567 5211 jones
        if (qformat == null || qformat.equals("xml")) {
2568
            response.setContentType("text/xml");
2569
            out.println(output);
2570
        } else {
2571
            try {
2572
                DBTransform trans = new DBTransform();
2573
                response.setContentType("text/html");
2574
                trans.transformXMLDocument(output,
2575
                        "message", "-//W3C//HTML//EN", qformat,
2576
                        out, null, null);
2577
            } catch (Exception e) {
2578 5319 jones
2579 5211 jones
                logMetacat.error("MetaCatServlet.handleUploadAction - General error: "
2580
                        + e.getMessage());
2581 5311 daigle
                e.printStackTrace(System.out);
2582 5211 jones
            }
2583
        }
2584
    }
2585
2586
    /*
2587
     * A method to handle set access action
2588
     */
2589
    protected void handleSetAccessAction(PrintWriter out, Hashtable<String, String[]> params,
2590
            String username, HttpServletRequest request, HttpServletResponse response) {
2591
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2592
2593
        String permission = null;
2594
        String permType = null;
2595
        String permOrder = null;
2596
        Vector<String> errorList = new Vector<String>();
2597
        String error = null;
2598
        Vector<String> successList = new Vector<String>();
2599
        String success = null;
2600
        boolean isEmlPkgMember = false;
2601
2602
        String[] docList = params.get("docid");
2603
        String[] principalList = params.get("principal");
2604
        String[] permissionList = params.get("permission");
2605
        String[] permTypeList = params.get("permType");
2606
        String[] permOrderList = params.get("permOrder");
2607
        String[] qformatList = params.get("qformat");
2608
        String[] accessBlock = params.get("accessBlock");
2609
2610
        if(accessBlock != null) {
2611
            if (docList == null) {
2612
                errorList.addElement("MetaCatServlet.handleSetAccessAction - Doc id missing.  Please check your parameter list, it should look like: "
2613
                    + "?action=setaccess&docid=<doc_id>&accessBlock=<access_section>");
2614
                outputResponse(successList, errorList, out);
2615
                return;
2616
            }
2617
2618
            try {
2619
                AccessControlForSingleFile accessControl =
2620
                    new AccessControlForSingleFile(docList[0]);
2621
                accessControl.insertPermissions(accessBlock[0]);
2622
                successList.addElement("MetaCatServlet.handleSetAccessAction - successfully replaced access block for doc id: " + docList[0]);
2623
            } catch(AccessControlException ace) {
2624
                errorList.addElement("MetaCatServlet.handleSetAccessAction - access control error when setting " +
2625
                    "access block: " + ace.getMessage());
2626
            }
2627
            outputResponse(successList, errorList, out);
2628
            return;
2629
        }
2630
2631
        // Make sure the parameter is not null
2632
        if (docList == null || principalList == null || permTypeList == null
2633
                || permissionList == null) {
2634
            error = "MetaCatServlet.handleSetAccessAction - Please check your parameter list, it should look like: "
2635
                    + "?action=setaccess&docid=pipeline.1.1&principal=public"
2636
                    + "&permission=read&permType=allow&permOrder=allowFirst";
2637
            errorList.addElement(error);
2638
            outputResponse(successList, errorList, out);
2639
            return;
2640
        }
2641
2642
        // Only select first element for permission, type and order
2643
        permission = permissionList[0];
2644
        permType = permTypeList[0];
2645
        if (permOrderList != null) {
2646
            permOrder = permOrderList[0];
2647
        }
2648
2649
        // Get package doctype set
2650
        Vector<String> packageSet = null;
2651
        try {
2652
            packageSet =
2653
                MetacatUtil.getOptionList(PropertyService.getProperty("xml.packagedoctypeset"));
2654
        } catch (PropertyNotFoundException pnfe) {
2655
            logMetacat.error("MetaCatServlet.handleSetAccessAction - Could not find package doctype set.  Setting to null: "
2656
                    + pnfe.getMessage());
2657
        }
2658
        //debug
2659
        if (packageSet != null) {
2660
            for (int i = 0; i < packageSet.size(); i++) {
2661
                logMetacat.debug("MetaCatServlet.handleSetAccessAction - doctype in package set: "
2662
                        + packageSet.elementAt(i));
2663
            }
2664
        }
2665
2666
        // handle every accessionNumber
2667
        for (int i = 0; i < docList.length; i++) {
2668
            String docid = docList[i];
2669
            if (docid.startsWith("urn:")) {
2670
                try {
2671
                    String actualDocId = LSIDUtil.getDocId(docid, false);
2672
                    docid = actualDocId;
2673
                } catch (ParseLSIDException ple) {
2674
                    logMetacat.error("MetaCatServlet.handleSetAccessAction - " +
2675 5311 daigle
                            "could not parse lsid: " + docid + " : " + ple.getMessage());
2676
                    ple.printStackTrace(System.out);
2677 5211 jones
                }
2678
            }
2679
2680
            String accessionNumber = docid;
2681
            String owner = null;
2682
            String publicId = null;
2683
            // Get document owner and public id
2684
            try {
2685
                owner = getFieldValueForDoc(accessionNumber, "user_owner");
2686
                publicId = getFieldValueForDoc(accessionNumber, "doctype");
2687
            } catch (Exception e) {
2688
                logMetacat.error("MetaCatServlet.handleSetAccessAction - Error in handleSetAccessAction: "
2689
                        + e.getMessage());
2690 5311 daigle
                e.printStackTrace(System.out);
2691 5211 jones
                error = "Error in set access control for document - " + accessionNumber + e.getMessage();
2692
                errorList.addElement(error);
2693
                continue;
2694
            }
2695
            //check if user is the owner. Only owner can do owner
2696
            if (username == null || owner == null || !username.equals(owner)) {
2697
                error = "User - " + username + " does not have permission to set "
2698
                        + "access control for docid - " + accessionNumber;
2699
                errorList.addElement(error);
2700
                continue;
2701
            }
2702
2703
            //*** Find out if the document is a Member of an EML package.
2704
            //*** (for efficiency, only check if it isn't already true
2705
            //*** for the case of multiple files).
2706
            if (isEmlPkgMember == false)
2707
                isEmlPkgMember = (DBUtil.findDataSetDocIdForGivenDocument(accessionNumber) != null);
2708
2709
            // If docid publicid is BIN data file or other beta4, 6 package document
2710
            // we could not do set access control. Because we don't want inconsistent
2711
            // to its access docuemnt
2712
            if (publicId != null && packageSet != null
2713
                    && packageSet.contains(publicId) && isEmlPkgMember) {
2714
                error = "Could not set access control to document " + accessionNumber
2715
                        + "because it is in a pakcage and it has a access file for it";
2716
                errorList.addElement(error);
2717
                continue;
2718
            }
2719
2720
            // for every principle
2721
            for (int j = 0; j < principalList.length; j++) {
2722
                String principal = principalList[j];
2723
                try {
2724
                    //insert permission
2725
                    AccessControlForSingleFile accessControl =
2726
                        new AccessControlForSingleFile(accessionNumber);
2727
                    accessControl.insertPermissions(principal, Long.valueOf(permission), permType, permOrder);
2728
                } catch (Exception ee) {
2729
                    logMetacat.error("MetaCatServlet.handleSetAccessAction - Error inserting permission: "
2730
                            + ee.getMessage());
2731 5311 daigle
                    ee.printStackTrace(System.out);
2732 5211 jones
                    error = "Failed to set access control for document "
2733
                            + accessionNumber + " because " + ee.getMessage();
2734
                    errorList.addElement(error);
2735
                    continue;
2736
                }
2737
            }
2738
2739
            //force replication when this action is called
2740
            boolean isXml = true;
2741
            if (publicId.equalsIgnoreCase("BIN")) {
2742
                isXml = false;
2743
            }
2744
            ForceReplicationHandler frh =
2745
                new ForceReplicationHandler(accessionNumber, isXml, null);
2746
            logMetacat.debug("MetaCatServlet.handleSetAccessAction - ForceReplicationHandler created: " + frh.toString());
2747
2748
        }
2749
        successList.addElement("MetaCatServlet.handleSetAccessAction - successfully added individual access for doc id: " + docList[0]);
2750
2751
        if (params.get("forwardto")  != null) {
2752
            try {
2753
                RequestUtil.forwardRequest(request, response, params);
2754
            } catch (MetacatUtilException mue) {
2755
                logMetacat.error("metaCatServlet.handleSetAccessAction - could not forward " +
2756
                        "request. Sending output to response writer");
2757 5311 daigle
                mue.printStackTrace(System.out);
2758 5211 jones
                outputResponse(successList, errorList, out);
2759
            }
2760
        } else {
2761
            outputResponse(successList, errorList, out);
2762
        }
2763
    }
2764
2765
    /*
2766
     * A method try to determin a docid's public id, if couldn't find null will
2767
     * be returned.
2768
     */
2769
    private String getFieldValueForDoc(String accessionNumber, String fieldName)
2770
    throws Exception {
2771
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2772
        if (accessionNumber == null || accessionNumber.equals("")
2773
        || fieldName == null || fieldName.equals("")) { throw new Exception(
2774
                "Docid or field name was not specified"); }
2775
2776
        PreparedStatement pstmt = null;
2777
        ResultSet rs = null;
2778
        String fieldValue = null;
2779
        String docId = null;
2780
        DBConnection conn = null;
2781
        int serialNumber = -1;
2782
2783
        // get rid of revision if access number has
2784
        docId = DocumentUtil.getDocIdFromString(accessionNumber);
2785
        try {
2786
            //check out DBConnection
2787
            conn = DBConnectionPool
2788
                    .getDBConnection("MetaCatServlet.getPublicIdForDoc");
2789
            serialNumber = conn.getCheckOutSerialNumber();
2790
            pstmt = conn.prepareStatement("SELECT " + fieldName
2791
                    + " FROM xml_documents " + "WHERE docid = ? ");
2792
2793
            pstmt.setString(1, docId);
2794
            pstmt.execute();
2795
            rs = pstmt.getResultSet();
2796
            boolean hasRow = rs.next();
2797
        //    int perm = 0;
2798
            if (hasRow) {
2799
                fieldValue = rs.getString(1);
2800
            } else {
2801
                throw new Exception("Could not find document: "
2802
                        + accessionNumber);
2803
            }
2804
        } catch (Exception e) {
2805
            logMetacat.error("MetaCatServlet.getFieldValueForDoc - General error: "
2806
                    + e.getMessage());
2807
            throw e;
2808
        } finally {
2809
            try {
2810
                rs.close();
2811
                pstmt.close();
2812
2813
            } finally {
2814
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2815
            }
2816
        }
2817
        return fieldValue;
2818
    }
2819
2820
    /*
2821
     * Get the list of documents from the database and return the list in an
2822
     * Vector of identifiers.
2823
     *
2824
     * @ returns the array of identifiers
2825
     */
2826
    private Vector<String> getDocumentList() throws SQLException {
2827
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2828
        Vector<String> docList = new Vector<String>();
2829
        PreparedStatement pstmt = null;
2830
        ResultSet rs = null;
2831
        DBConnection conn = null;
2832
        int serialNumber = -1;
2833
2834
        try {
2835
            //check out DBConnection
2836
            conn = DBConnectionPool
2837
                    .getDBConnection("MetaCatServlet.getDocumentList");
2838
            serialNumber = conn.getCheckOutSerialNumber();
2839
            pstmt = conn.prepareStatement("SELECT docid, rev"
2840
                    + " FROM xml_documents ");
2841
            pstmt.execute();
2842
            rs = pstmt.getResultSet();
2843
            while (rs.next()) {
2844
                String docid = rs.getString(1);
2845
                String rev = rs.getString(2);
2846
                docList.add(docid + "." + rev);
2847
            }
2848
        } catch (SQLException e) {
2849
            logMetacat.error("MetaCatServlet.getDocumentList - General exception: "
2850
                    + e.getMessage());
2851
            throw e;
2852
        } finally {
2853
            try {
2854
                rs.close();
2855
                pstmt.close();
2856
2857
            } catch (SQLException se) {
2858
                logMetacat.error("MetaCatServlet.getDocumentList - General exception: "
2859
                        + se.getMessage());
2860
                throw se;
2861
            } finally {
2862
                DBConnectionPool.returnDBConnection(conn, serialNumber);
2863
            }
2864
        }
2865
        return docList;
2866
    }
2867
2868
    /*
2869
     * A method to output setAccess action result
2870
     */
2871
    private void outputResponse(Vector<String> successList, Vector<String> errorList,
2872
            PrintWriter out) {
2873
        boolean error = false;
2874
        boolean success = false;
2875
        // Output prolog
2876
        out.println(PROLOG);
2877
        // output success message
2878
        if (successList != null) {
2879
            for (int i = 0; i < successList.size(); i++) {
2880
                out.println(SUCCESS);
2881
                out.println(successList.elementAt(i));
2882
                out.println(SUCCESSCLOSE);
2883
                success = true;
2884
            }
2885
        }
2886
        // output error message
2887
        if (errorList != null) {
2888
            for (int i = 0; i < errorList.size(); i++) {
2889
                out.println(ERROR);
2890
                out.println(errorList.elementAt(i));
2891
                out.println(ERRORCLOSE);
2892
                error = true;
2893
            }
2894
        }
2895
2896
        // if no error and no success info, send a error that nothing happened
2897
        if (!error && !success) {
2898
            out.println(ERROR);
2899
            out.println("Nothing happend for setaccess action");
2900
            out.println(ERRORCLOSE);
2901
        }
2902
    }
2903
2904
    /*
2905
     * If the given docid only have one seperter, we need
2906
     * append rev for it. The rev come from xml_documents
2907
     */
2908 5298 jones
    private static String appendRev(String docid) throws PropertyNotFoundException, SQLException, McdbDocNotFoundException {
2909 5211 jones
//        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2910
        String newAccNum = null;
2911
        String separator = PropertyService.getProperty("document.accNumSeparator");
2912
        int firstIndex = docid.indexOf(separator);
2913
        int lastIndex = docid.lastIndexOf(separator);
2914
        if (firstIndex == lastIndex) {
2915
2916
            //only one seperater
2917
            int rev = DBUtil.getLatestRevisionInDocumentTable(docid);
2918
            if (rev == -1) {
2919 5298 jones
                throw new McdbDocNotFoundException("the requested docid '"
2920 5211 jones
                        + docid+ "' does not exist");
2921
            } else {
2922
                newAccNum = docid+ separator+ rev;
2923
            }
2924
        } else {
2925
            // in other suituation we don't change the docid
2926
            newAccNum = docid;
2927
        }
2928
        //logMetacat.debug("The docid will be read is "+newAccNum);
2929
        return newAccNum;
2930
    }
2931
2932
    /**
2933
     * Schedule the sitemap generator to run periodically and update all
2934
     * of the sitemap files for search indexing engines.
2935
     *
2936
     * @param request a servlet request, from which we determine the context
2937
     */
2938
    protected void scheduleSitemapGeneration(HttpServletRequest request) {
2939
        Logger logMetacat = Logger.getLogger(MetaCatServlet.class);
2940
        if (!_sitemapScheduled) {
2941
            String directoryName = null;
2942
            String skin = null;
2943
            long sitemapInterval = 0;
2944
2945
            try {
2946
                directoryName = SystemUtil.getContextDir() + FileUtil.getFS() + "sitemaps";
2947
                skin = PropertyService.getProperty("application.default-style");
2948
                sitemapInterval =
2949
                    Integer.parseInt(PropertyService.getProperty("sitemap.interval"));
2950
            } catch (PropertyNotFoundException pnfe) {
2951
                logMetacat.error("MetaCatServlet.scheduleSitemapGeneration - Could not run site map generation because property "
2952
                        + "could not be found: " + pnfe.getMessage());
2953
            }
2954
2955
            File directory = new File(directoryName);
2956
            directory.mkdirs();
2957
            String urlRoot = request.getRequestURL().toString();
2958
            Sitemap smap = new Sitemap(directory, urlRoot, skin);
2959
            long firstDelay = 60*1000;   // 60 seconds delay
2960
            timer.schedule(smap, firstDelay, sitemapInterval);
2961
            _sitemapScheduled = true;
2962
        }
2963
    }
2964
2965
    /**
2966
     * @param sitemapScheduled toggle the _sitemapScheduled flag
2967
     */
2968 5311 daigle
    public void set_sitemapScheduled(boolean sitemapScheduled) {
2969 5211 jones
        _sitemapScheduled = sitemapScheduled;
2970
    }
2971
2972
}