Project

General

Profile

1
/*
2
 * ClientViewHelper.java
3
 *
4
 * Created on June 25, 2007, 9:57 AM
5
 *
6
 * To change this template, choose Tools | Template Manager
7
 * and open the template in the editor.
8
 */
9

    
10
package edu.ucsb.nceas.metacat.clientview;
11

    
12
import com.oreilly.servlet.multipart.FilePart;
13
import com.oreilly.servlet.multipart.MultipartParser;
14
import com.oreilly.servlet.multipart.ParamPart;
15
import com.oreilly.servlet.multipart.Part;
16
import edu.ucsb.nceas.metacat.MetaCatUtil;
17
import edu.ucsb.nceas.metacat.client.MetacatClient;
18
import edu.ucsb.nceas.metacat.client.MetacatFactory;
19
import edu.ucsb.nceas.metacat.client.MetacatInaccessibleException;
20
import edu.ucsb.nceas.utilities.XMLUtilities;
21
import java.io.BufferedReader;
22
import java.io.ByteArrayOutputStream;
23
import java.io.IOException;
24
import java.io.InputStream;
25
import java.io.InputStreamReader;
26
import java.io.Reader;
27
import java.io.StringReader;
28
import java.util.HashMap;
29
import java.util.Iterator;
30
import java.util.Properties;
31
import java.util.TreeMap;
32
import java.util.Vector;
33
import javax.servlet.http.HttpServletRequest;
34
import javax.servlet.http.HttpServletResponse;
35
import javax.servlet.http.HttpSession;
36
import javax.xml.xpath.XPath;
37
import javax.xml.xpath.XPathConstants;
38
import javax.xml.xpath.XPathExpressionException;
39
import javax.xml.xpath.XPathFactory;
40
import org.w3c.dom.Document;
41
import org.w3c.dom.Node;
42
import org.w3c.dom.NodeList;
43

    
44
/**
45
 *
46
 * @author barteau
47
 */
48
public class ClientViewHelper {
49
    private XPath                                       xpath = XPathFactory.newInstance().newXPath();
50
    private HttpSession                                 clientSession;
51
    private ClientView                                  clientViewBean = null;
52
    private MetacatClient                               metacatClient = null;
53
    private boolean                                     loggedIn = false;
54
    private Document                                    metadataDoc = null;
55
    private int                                         sizeLimit;
56
    private String                                      contactName = "";
57
    
58
    private static final String                         LDAP_TEMPLATE = "uid=%1s,o=%2s,dc=ecoinformatics,dc=org";
59
    
60
    public static final String                          DOWNLOAD_ACTION = "Download";
61
    
62
    /**
63
     * Creates a new instance of ClientViewHelper
64
     */
65
    public ClientViewHelper(HttpServletRequest request) throws MetacatInaccessibleException {
66
        String                              metacatPath = "http://%1s%2s/metacat";
67
        String                              host, context, button, tmp;
68
        
69
        clientSession = request.getSession();
70
        
71
        host = request.getHeader("host");
72
        context = request.getContextPath();
73
        //metacatPath = String.format(metacatPath, host, context);
74
        tmp = metacatPath.replaceFirst("%1s", host);
75
        metacatPath = tmp.replaceFirst("%2s", context);
76
        metacatClient = (MetacatClient) MetacatFactory.createMetacatConnection(metacatPath);
77
        sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit"))).intValue();
78
    }
79
    
80
    public String clientRequest(HttpServletRequest request, HttpServletResponse response)  {
81
        String                              result = null, action, message, serverResponse;
82
        String                              button, contentType, posted_ldapUserName, tmp;
83
        MultipartParser                     multipartParser;
84
        int                                 fileIdx;
85
        
86
        if (clientViewBean == null)
87
            clientViewBean = (ClientView) clientSession.getAttribute(ClientView.CLIENT_VIEW_BEAN);
88
        
89
        if (clientViewBean != null) {
90
            action = clientViewBean.getAction();
91
            contentType = request.getContentType();
92
            
93
            //*** BEGIN: manual bind params to bean (if we arrived here via the ClientViewHelper.jspx).
94
            if (action == null || action.equals("")) {
95
                if (contentType != null && contentType.contains("multipart/form-data")) {
96
                    action = "Upload";
97
                } else {
98
                    action = request.getParameter("action");
99
                    clientViewBean.setAction(action);
100
                    clientViewBean.setDocId(request.getParameter("docid"));
101
                    clientViewBean.setMetaFileDocId(request.getParameter("metadataDocId"));
102
                    clientViewBean.setQformat(request.getParameter("qformat"));
103
                }
104
            }
105
            //*** END: manual bind params to bean.
106
            if (action != null) {
107
                try {
108
                    if (action.equals("Login")) {
109
                        //posted_ldapUserName = String.format(LDAP_TEMPLATE, clientViewBean.getUsername(), clientViewBean.getOrganization());
110
                        tmp = LDAP_TEMPLATE.replaceFirst("%1s", clientViewBean.getUsername());
111
                        posted_ldapUserName = tmp.replaceFirst("%2s", clientViewBean.getOrganization());
112
                        
113
                        serverResponse = metacatClient.login(posted_ldapUserName, clientViewBean.getPassword());
114
                        setLoggedIn(serverResponse);
115
                        message = parseXml("message", serverResponse);
116
                        contactName = parseXml("name", serverResponse);
117
                        clientViewBean.setMessage(ClientView.LOGIN_MESSAGE, message);
118
                        clientViewBean.setMessage(ClientView.UPLOAD_MESSAGE, "");
119
                        if (isLoggedIn()) {
120
                            clientViewBean.setSessionid(metacatClient.getSessionId());
121
                        }
122
                        //*** Now that the action has been processed, clear it.
123
                        clientViewBean.setAction("");
124
                    } else if (action.equals("Logout")) {
125
                        message = metacatClient.logout();
126
                        setLoggedIn(message);
127
                        message = parseXml("message", message);
128
                        clientViewBean.setMessage(ClientView.LOGIN_MESSAGE, message);
129
                        clientViewBean.setMessage(ClientView.UPLOAD_MESSAGE, "");
130
                        if (!isLoggedIn()) {
131
                            clientViewBean.setUsername("");
132
                            clientViewBean.setPassword("");
133
                            clientViewBean.setOrganization("");
134
                            clientViewBean.setSessionid(null);
135
                        }
136
                        //*** Now that the action has been processed, clear it.
137
                        clientViewBean.setAction("");
138
                        
139
                    } else if (action.equals("Delete")) {
140
                        
141
                        ClientFgdcHelper.clientDeleteRequest(clientViewBean, this);
142
                        clientViewBean.setAction("read"); //*** Set for re-query.
143
                        //*** Note: the clientViewBean will already have the updated Meta Doc Id.
144
                    } else if (action.equals("Upload")) {
145
                        message = "";
146
                        //*** Only process request if a file upload.
147
                        if (isLoggedIn()) {
148
                            //*** Init the MultipartParser.
149
                            multipartParser = new MultipartParser(request, sizeLimit * 1024 * 1024);
150
                            message = handlePackageUpload(clientViewBean, multipartParser);
151
                        }
152
                        clientViewBean.setMessage(ClientView.UPLOAD_MESSAGE, message);
153
                        //*** Now that the action has been processed, clear it.
154
                        clientViewBean.setAction("");
155
                        
156
                    } else if (action.equals("Update")) {
157
                        System.out.println("This is not implemented here.  Call ClientViewHelper.jspx");
158
                    } else if (action.equals("Scope")) {
159
                        message = handleDocIdSelect();
160
                        clientViewBean.setMessage(ClientView.SELECT_MESSAGE, message);
161
                    } else if (action.equals("Download")) {
162
                        System.out.println("ClientViewHelper.clientRequest: action = " + action);
163
                        download(clientViewBean, response);
164
                    }
165
                    
166
                } catch (Exception ex) {
167
                    message = ex.getMessage();
168
                    clientViewBean.setMessage(ClientView.ERROR_MESSAGE, message);
169
                    ex.printStackTrace();
170
                }
171
            }
172
        } else {
173
            System.out.println("ClientViewHelper.clientRequest: ClientView bean is not instantiated.");
174
        }
175
        return(result);
176
    }
177
    
178
    /**
179
     * This is a convenience method to reduce the amount of code in a Metacat Client.
180
     * It handles creating/reusing (per session) an instance of a ClientViewHelper.
181
     * @param request Since this is intended to be used by an Http client, it is passed the
182
     * available "request" variable (the HttpServletRequest).
183
     * @throws edu.ucsb.nceas.metacat.client.MetacatInaccessibleException Received by MetacatFactory.
184
     * @return ClientViewHelper instance.
185
     */
186
    public static ClientViewHelper clientViewHelperInstance(HttpServletRequest request) {
187
        ClientViewHelper                        result;
188
        
189
        result = (ClientViewHelper) request.getSession().getAttribute("ClientViewHelper");
190
        if (result == null) {
191
            try {
192
                result = new ClientViewHelper(request);
193
                request.getSession().setAttribute("ClientViewHelper", result);
194
            } catch (MetacatInaccessibleException ex) {
195
                ex.printStackTrace();
196
            }
197
        }
198
        
199
        return(result);
200
    }
201
    
202
    /**
203
     * A convenience method to be used by client code that requires
204
     * the user to be logged in.  NOTE: setUser() must have been called first,
205
     * otherwise it will always return false.
206
     * @return boolean  true if user has logged in for this session, false otherwise.
207
     */
208
    public boolean isLoggedIn() {
209
        return(loggedIn);
210
    }
211
    
212
    /**
213
     * After calling "login(ldapUserName, pwd)", call this with the username
214
     * and servers response message.  You can than use isLoggedIn() to determine if
215
     * the user is logged in, getLoginResponseElement(), etc.  The user name will also
216
     * used by calls to doMetadataUpload() for Document Id creation (scope).
217
     * @param userName User name
218
     * @param serverResponse XML login response sent from Metacat.
219
     */
220
    public void setLoggedIn(String serverResponse) {
221
        loggedIn = (serverResponse != null && serverResponse.contains("login"));
222
    }
223
    
224
    public String parseXml(String elementName, String xml) {
225
        String                      result = null;
226
        Document                    doc;
227
        
228
        try {
229
            doc = XMLUtilities.getXMLReaderAsDOMDocument(new StringReader(xml));
230
            result = (String) xpath.evaluate(elementName, doc.getDocumentElement(), XPathConstants.STRING);
231
            if (result != null)
232
                result = result.trim();
233
        } catch (IOException ex) {
234
            ex.printStackTrace();
235
        } catch (XPathExpressionException ex) {
236
            ex.printStackTrace();
237
        }
238
        return(result);
239
    }
240
    
241
    public String handleDocIdSelect() {
242
        String                              result = "";
243
        TreeMap                             allDocIds;
244
        
245
        if (!clientViewBean.getPathValue().equals("")) {
246
            allDocIds = getSelectQueryMap();
247
            result = ClientHtmlHelper.mapToHtmlSelect(allDocIds, "docId", "width: 240", 10);
248
        }
249
        return(result);
250
    }
251
    
252
    /**
253
     * Handles metadata file and data file uploads for inserting new
254
     * Metacat data packages.  Note: if content type is not "multipart/form-data",
255
     * nothing will happen.
256
     * @param request HTTP request.
257
     * @return A 1-line status message for the user.
258
     */
259
    public String handlePackageUpload(ClientView clientViewBean, MultipartParser multipartParser) throws Exception {
260
        String                      result = "", contentType, formatType;
261
        String                      lastDocId, nextDocId, metaDocId, metaFileName;
262
        String                      fileInfo[];
263
        Reader                      reader;
264
        int                         sizeLimit, idx;
265
        InputStream                 inputStream;
266
        HashMap                     paramsMap, dataDocIDs;
267
        StringBuffer                fileName;
268
        boolean                     sendIt;
269
        
270
        //*** Get the First file, which should be the metadata file.
271
        paramsMap = new HashMap();
272
        fileName = new StringBuffer();
273
        inputStream = getNextInputStream(multipartParser, fileName, paramsMap);
274
        metaFileName = fileName.toString();
275
        if (metaFileName.toLowerCase().endsWith(".xml")) {
276
            //*** Keep it here for updating.
277
            setMetadataDoc(inputStream);
278
            //*** Get the Metadata File's DOC ID.
279
            lastDocId = getMetacatClient().getLastDocid(clientViewBean.getUsername());
280
            metaDocId = lastDocId = nextDocId(lastDocId, clientViewBean.getUsername());
281
            
282
            //*** Loop thru all of the data files, get fileName and inputStream.
283
            dataDocIDs = new HashMap();
284
            fileName = new StringBuffer();
285
            while ((inputStream = getNextInputStream(multipartParser, fileName, paramsMap)) != null) {
286
                //*** Get the data file's DOC ID.
287
                nextDocId = nextDocId(lastDocId, clientViewBean.getUsername());
288
                
289
                fileInfo = parseFileInfo(fileName.toString());
290
                dataDocIDs.put(nextDocId, fileInfo);
291
                //*** Upload the data file to metacat.
292
                getMetacatClient().upload(nextDocId, fileName.toString(), inputStream, Integer.MAX_VALUE);
293
                
294
                lastDocId = nextDocId;
295
                fileName = new StringBuffer();
296
            }
297
            
298
            if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
299
                sendIt = ClientFgdcHelper.handlePackageUpload(metaDocId, dataDocIDs, contactName, metaFileName, getMetadataDoc());
300
            } else {
301
                //TODO add other types of metadata grammars here...
302
                System.out.println("ClientViewHelper.handlePackageUpload: not an FGDC file = " + fileName);
303
                result = fileName + " is not an FGDC file.  Files not uploaded.";
304
                sendIt = false;
305
            }
306
            
307
            if (sendIt) {
308
                //*** Upload the metadata file to metacat.
309
                reader = XMLUtilities.getDOMTreeAsReader(metadataDoc.getDocumentElement(), false);
310
                getMetacatClient().insert(metaDocId, reader, null);
311
                
312
                result = "MetaCat Package Inserted:  the Document Identifier is " + metaDocId;
313
                reader.close();
314
                
315
                //*** One last detail...grant the public read access.
316
                if (paramsMap.containsKey("publicAccess"))
317
                    getMetacatClient().setAccess(metaDocId, "public", "read", "allow", "allowFirst");
318
            }
319
            
320
        } else {
321
            result = "The first file must be an XML Metadata file.  Files not uploaded.";
322
        }
323
        if (inputStream != null)
324
            inputStream.close();
325
        return(result);
326
    }
327
    
328
    public String handleFileUpdate(MultipartParser multipartParser) throws Exception {
329
        String                      result = "", fNm, action, lastDocId, newDocId, xPathQuery, qFrmt;
330
        InputStream                 inputStream;
331
        HashMap                     paramsMap;
332
        StringBuffer                fileName;
333
        Iterator                    iterIt;
334
        boolean                     sendIt;
335
        String                      metadataDocId, fileInfo[];
336
        
337
        paramsMap = new HashMap();
338
        fileName = new StringBuffer();
339
        if ((inputStream = getNextInputStream(multipartParser, fileName, paramsMap)) != null) {
340
            action = (String) paramsMap.get("action");
341
            //*** Get the Doc Id.
342
            lastDocId = (String) paramsMap.get("docid");
343
            //*** Get the metadata Doc Id.
344
            metadataDocId = (String) paramsMap.get("metadataDocId");
345
            //*** Get the qformat.
346
            qFrmt = (String) paramsMap.get("qformat");
347
            
348
            fNm = fileName.toString();
349
            
350
            try {
351
                if (lastDocId.equals(metadataDocId)) { //*** This is the metadata file.
352
                    //*** Keep it here for updating.
353
                    setMetadataDoc(inputStream);
354
                    if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
355
                        clientViewBean.setContentStandard(ClientView.FEDERAL_GEOGRAPHIC_DATA_COMMITTEE);
356
                        if (!ClientFgdcHelper.hasMetacatInfo(lastDocId, getMetadataDoc())) {
357
                            
358
                            //*** Save the Doc Id for re-query.
359
                            clientViewBean.setMetaFileDocId(lastDocId);
360
                            clientViewBean.setAction("read"); //*** Set for re-query.
361
                            result = "Update not performed: the Metadata file has no prior Metacat info in it.";
362
                        } else {
363
                            xPathQuery = ClientFgdcHelper.XPATH_QUERY_TEMPLATE.replaceFirst("%1s", lastDocId);
364
                            newDocId = updateMetadataDoc(lastDocId, xPathQuery, fNm);
365
                            
366
                            //*** Save the Doc Id for re-query.
367
                            clientViewBean.setMetaFileDocId(newDocId);
368
                            clientViewBean.setAction("read"); //*** Set for re-query.
369
                            //result = makeRedirectUrl(newDocId, qFrmt);
370
                            result = "Updated to new document (from " + lastDocId + " to " + newDocId + ")";
371
                        }
372
                    } else {
373
                        //***TODO This is EML.
374
                        clientViewBean.setContentStandard(ClientView.ECOLOGICAL_METADATA_LANGUAGE);
375
                        
376
                        //*** Save the Doc Id for re-query.
377
                        clientViewBean.setMetaFileDocId(lastDocId);
378
                        clientViewBean.setAction("read"); //*** Set for re-query.
379
                        result = "Currently this functionality only supports FGDC metadata.";
380
                    }
381
                } else {
382
                    //*** This is a data file.
383
                    //*** Query for the metadata, we need to update it with the new data file doc id.
384
                    setMetadataDoc(metadataDocId);
385
                    
386
                    if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
387
                        clientViewBean.setContentStandard(ClientView.FEDERAL_GEOGRAPHIC_DATA_COMMITTEE);
388
                        fileInfo = parseFileInfo(fNm);
389
                        
390
                        xPathQuery = ClientFgdcHelper.FGDC_DATA_FILE_QUERY_XPATH.replaceFirst("%1s", lastDocId);
391
                        newDocId = nextVersion(lastDocId, xPathQuery);
392
                        ClientFgdcHelper.updateFileNameAndType(getMetadataDoc().getDocumentElement(), newDocId, fileInfo);
393
                        //*** Upload the data file to metacat.
394
                        result = getMetacatClient().upload(newDocId, fNm, inputStream, Integer.MAX_VALUE);
395
                        System.out.println("ClientViewHelper.handleFileUpdate: upload returned " + result);
396
                        
397
                        
398
                        //*** Upload the metadata file to metacat.
399
                        xPathQuery = ClientFgdcHelper.XPATH_QUERY_TEMPLATE.replaceFirst("%1s", metadataDocId);
400
                        newDocId = updateMetadataDoc(metadataDocId, xPathQuery, null);
401
                        
402
                        //*** Save the new meta Doc Id for re-query.
403
                        clientViewBean.setMetaFileDocId(newDocId);
404
                        clientViewBean.setAction("read"); //*** Set for re-query.
405
                        //result = makeRedirectUrl(newDocId, qFrmt);
406
                        result = "Updated to new document (from " + lastDocId + " to " + newDocId + ")";
407
                        
408
                    } else {
409
                        //***TODO This is EML.
410
                        clientViewBean.setContentStandard(ClientView.ECOLOGICAL_METADATA_LANGUAGE);
411
                        
412
                        //*** Save the old meta Doc Id for re-query.
413
                        clientViewBean.setMetaFileDocId(metadataDocId);
414
                        clientViewBean.setAction("read"); //*** Set for re-query.
415
                        result = "Currently this functionality only supports FGDC metadata.";
416
                    }
417
                }
418
            } catch (java.io.IOException ex) {
419
                ex.printStackTrace();
420
            }
421
        } else {
422
            result = "Please enter the updated file path/name.";
423
        }
424
        clientViewBean.setMessage(ClientView.UPDATE_MESSAGE, result);
425
        return(result);
426
    }
427
    
428
    private String updateMetadataDoc(String lastDocId, String docIdPath, String origFileName) {
429
        String                      newDocId = null;
430
        Reader                      reader;
431
        
432
        //*** Update the metadata with the new Doc Id version.
433
        try {
434
            newDocId = nextVersion(lastDocId, docIdPath);
435
            if (origFileName != null) {
436
                if (clientViewBean.getContentStandard().equals(ClientView.FEDERAL_GEOGRAPHIC_DATA_COMMITTEE))
437
                    ClientFgdcHelper.updateMetadataFileName(getMetadataDoc().getDocumentElement(), newDocId, origFileName);
438
                else
439
                    ; //TODO EML, etc.
440
            }
441
            //*** Upload the metadata file to metacat.
442
            reader = XMLUtilities.getDOMTreeAsReader(getMetadataDoc().getDocumentElement(), false);
443
            getMetacatClient().update(newDocId, reader, null);
444
            reader.close();
445
        } catch (Exception ex) {
446
            ex.printStackTrace();
447
        }
448
        return(newDocId);
449
    }
450
    
451
    private InputStream getNextInputStream(MultipartParser multipartParser, StringBuffer fileName, HashMap paramsMap)
452
    throws IOException {
453
        InputStream                     result = null;
454
        Part                            part;
455
        String                          parmName = null, value = null, fnam;
456
        
457
        while ((part = multipartParser.readNextPart()) != null) {
458
            if (part.isParam()) {
459
                parmName = part.getName();
460
                value = ((ParamPart) part).getStringValue();
461
                paramsMap.put(parmName, value);
462
                System.out.println("ClientViewHelper.getNextInputStream: parmName = " + parmName + "  value = " + value);
463
                
464
            } else if (part.isFile()) {
465
                fnam = ((FilePart) part).getFileName();
466
                if (fnam != null && !fnam.equals("")) {
467
                    //*** File name is passed back via StringBuffer fileName param.
468
                    fileName.append(fnam);
469
                    result = ((FilePart) part).getInputStream();
470
                    System.out.println("ClientViewHelper.getNextInputStream: fileName = " + fileName + "  inputStream = " + result.toString());
471
                    break;
472
                }
473
            }
474
        }
475
        return(result);
476
    }
477
    
478
    private void getRemainingParameters(MultipartParser multipartParser, HashMap paramsMap)
479
    throws IOException {
480
        InputStream                     result = null;
481
        Part                            part;
482
        String                          parmName = null, value = null, fnam;
483
        
484
        while ((part = multipartParser.readNextPart()) != null) {
485
            if (part.isParam()) {
486
                parmName = part.getName();
487
                value = ((ParamPart) part).getStringValue();
488
                paramsMap.put(parmName, value);
489
                System.out.println("ClientViewHelper.getNextInputStream: parmName = " + parmName + "  value = " + value);
490
            }
491
        }
492
    }
493
    
494
    /**
495
     * Queries Metacat for document listings, and returns the results in a TreeMap,
496
     * where the key is the Doc Id, and the value is the Create Date.  If the document
497
     * contains the specified 'returnfield', an addtional entry will be created with
498
     * the value being a Vector of sub-DocId's.  The key of this entry will be the
499
     * original DocId with some addtional text added.
500
     * Reads bean properties 'pathExpr' (String[]), 'pathValue' (String)
501
     * and 'returnfield' (String).
502
     * @return TreeMap
503
     */
504
    public TreeMap getSelectQueryMap() {
505
        TreeMap                         result;
506
        Document                        doc;
507
        NodeList                        nodeLst, subNodeLst;
508
        Node                            node, subNode;
509
        String                          key, val, paramExpr, paramVal;
510
        String                          value, returnFld;
511
        String                          path;
512
        Vector                          optGroup;
513
        final String                    DOCID_EXPR = "./docid";
514
        final String                    DOCNAME_EXPR = "./createdate";
515
        final String                    PARAM_EXPR = "./param[@name='%1s']";
516
        
517
        path = clientViewBean.getPathExpr();
518
        returnFld = clientViewBean.getReturnfield();
519
        value = clientViewBean.getPathValue();
520
        
521
        result = new TreeMap();
522
        //paramExpr = String.format(PARAM_EXPR, returnFld);
523
        paramExpr = PARAM_EXPR.replaceFirst("%1s", returnFld);
524
        //*** Query the database ***
525
        doc = query(path, value, returnFld);
526
        //*** Build the TreeMap to return ***
527
        try {
528
            nodeLst = (NodeList) xpath.evaluate("/resultset/document", doc, XPathConstants.NODESET);
529
            for (int i = 0; i < nodeLst.getLength(); i++) {
530
                node = nodeLst.item(i);
531
                key = xpath.evaluate(DOCID_EXPR, node);
532
                val = xpath.evaluate(DOCNAME_EXPR, node);
533
                result.put(key, key + " (" + val + ")");
534
                
535
                //*** returnfield values ***
536
                subNodeLst = (NodeList) xpath.evaluate(paramExpr, node, XPathConstants.NODESET);
537
                if (subNodeLst.getLength() > 0) {
538
                    optGroup = new Vector();
539
                    for (int k = 0; k < subNodeLst.getLength(); k++) {
540
                        subNode =  subNodeLst.item(k);
541
                        paramVal = xpath.evaluate("text()", subNode);
542
                        optGroup.add(paramVal);
543
                    }
544
                    result.put(key + " Data Files", optGroup);
545
                }
546
                
547
            }
548
        } catch (XPathExpressionException ex) {
549
            ex.printStackTrace();
550
        }
551
        return(result);
552
    }
553
    
554
    /**
555
     * Query metacat for documents that 'CONTAINS' the value at the specified XPath
556
     * expression.  Additionally, returns another non-standard field value.
557
     * Standard info contains: DocId, DocName, DocType, CreateDate, and UpdateDate.
558
     * @param pathExpr String contianing an XPath expression.
559
     * @param pathValue String containing a comparison value at the XPath expression.
560
     * @param returnFld String containing an XPath expression to a field which will be returned
561
     * in addition to the standard info.
562
     * @return DOM Document containing the results.
563
     */
564
    public Document query(String pathExpr, String pathValue, String returnFld) {
565
        Document                        result = null;
566
        InputStream                     response;
567
        BufferedReader                  buffy;
568
        Properties                      prop;
569
        
570
        try {
571
            prop = new Properties();
572
            prop.put("action", "query");
573
            prop.put("qformat", "xml");
574
            prop.put(pathExpr, pathValue);
575
            if (returnFld != null) {
576
                prop.put("returnfield", returnFld);
577
            }
578
            
579
            response = metacatClient.sendData(prop, null, null, 0);
580
            if (response != null) {
581
                buffy = new BufferedReader(new InputStreamReader(response));
582
                result = XMLUtilities.getXMLReaderAsDOMDocument(buffy);
583
            }
584
        } catch (IOException ex) {
585
            ex.printStackTrace();
586
        } catch (Exception ex) {
587
            ex.printStackTrace();
588
        }
589
        return(result);
590
    }
591
    
592
    public void setMetadataDoc(Document doc) {
593
        metadataDoc = doc;
594
    }
595
    
596
    public void setMetadataDoc(String docId) throws Exception {
597
        Document                        doc = null;
598
        BufferedReader                  buffy;
599
        Properties                      prop;
600
        InputStream                     response;
601
        
602
        //*** MetaCatServlet Properties: action, qformat and docid. ***
603
        prop = new Properties();
604
        prop.put("action", "read");
605
        prop.put("qformat", "xml");
606
        prop.put("docid", docId);
607
        response = metacatClient.sendData(prop, null, null, 0);
608
        if (response != null) {
609
            buffy = new BufferedReader(new InputStreamReader(response));
610
            doc = XMLUtilities.getXMLReaderAsDOMDocument(buffy);
611
            response.close();
612
        }
613
        setMetadataDoc(doc);
614
    }
615
    
616
    public void setMetadataDoc(InputStream ioStream) throws IOException {
617
        BufferedReader                          buffy;
618
        
619
        if (ioStream != null) {
620
            buffy = new BufferedReader(new InputStreamReader(ioStream));
621
            metadataDoc = XMLUtilities.getXMLReaderAsDOMDocument(buffy);
622
        }
623
    }
624
    
625
    public Document getMetadataDoc() {
626
        return(metadataDoc);
627
    }
628
    
629
    public String nextVersion(String lastDocId, String xPathQuery) throws XPathExpressionException {
630
        String                      result = null, tokens[], scope, ready2Split, tmp;
631
        int                         vers, docNum;
632
        final int                   LAST_TOKEN = 2;
633
        final String                TEMPLATE = "%1s.%2d.%3d";
634
        Node                        node;
635
        
636
        //*** Parse the last Doc Id, and increment the version number.
637
        if(lastDocId != null && lastDocId.contains(".")) {
638
            ready2Split = lastDocId.replace('.','~'); //*** This is necessary for the split to work.
639
            tokens = ready2Split.split("~");
640
            if(tokens.length > LAST_TOKEN && !tokens[LAST_TOKEN].equals("")) {
641
                scope = tokens[LAST_TOKEN - 2];
642
                docNum = Integer.parseInt(tokens[LAST_TOKEN - 1]);
643
                try {
644
                    vers = Integer.parseInt(tokens[LAST_TOKEN]);
645
                    //result = String.format(TEMPLATE, scope, docNum, 1 + vers);
646
                    tmp = TEMPLATE.replaceFirst("%1s", scope);
647
                    tmp = tmp.replaceFirst("%2d", String.valueOf(docNum));
648
                    result = tmp.replaceFirst("%3d", String.valueOf(vers + 1));
649
                    
650
                } catch (NumberFormatException ex) {
651
                    //*** In case the lastDocId has something other than a number.
652
                    //result = String.format(TEMPLATE, scope, docNum, 1);
653
                    tmp = TEMPLATE.replaceFirst("%1s", scope);
654
                    tmp = tmp.replaceFirst("%2d", String.valueOf(docNum));
655
                    result = tmp.replaceFirst("%3d", "1");
656
                }
657
            } else {
658
                //*** In case the lastDocId ends with a '.'
659
                result = lastDocId + "1";
660
            }
661
        } else {
662
            //*** In case of missing doc Id.
663
            result = null;
664
        }
665
        //*** Update the Doc Id in the metadata file.
666
        if (getMetadataDoc() != null) {
667
            node = (Node) xpath.evaluate(xPathQuery, getMetadataDoc().getDocumentElement(), XPathConstants.NODE);
668
            node.setTextContent(result);
669
        }
670
        return(result);
671
    }
672
    
673
    private String nextDocId(String lastDocId, String scope) {
674
        String                      result = null, tokens[], tmp;
675
        int                         vers;
676
        String                      template = scope.toLowerCase() + ".%1d.%2d";
677
        
678
        if(lastDocId != null && lastDocId.contains(".")) {
679
            lastDocId = lastDocId.replace('.','~'); //*** This is necessary for the split to work.
680
            tokens = lastDocId.split("~");
681
            if(tokens.length > 1 && !tokens[1].equals("")) {
682
                try {
683
                    vers = Integer.parseInt(tokens[1]);
684
                    //result = String.format(template, 1 + vers, 1);
685
                    tmp = template.replaceFirst("%1d", String.valueOf(1 + vers));
686
                    result = tmp.replaceFirst("%2d", "1");
687
                } catch (NumberFormatException ex) {
688
                    //*** In case the lastDocId has something other than a number.
689
                    //result = String.format(template, 1, 1);
690
                    tmp = template.replaceFirst("%1d", "1");
691
                    result = tmp.replaceFirst("%2d", "1");
692
                }
693
            } else {
694
                //*** In case the lastDocId ends with a '.'
695
                //result = String.format(template, 1, 1);
696
                tmp = template.replaceFirst("%1d", "1");
697
                result = tmp.replaceFirst("%2d", "1");
698
            }
699
        } else {
700
            //*** In case there isn't any doc Id's with the user name.
701
            //result = String.format(template, 1, 1);
702
            tmp = template.replaceFirst("%1d", "1");
703
            result = tmp.replaceFirst("%2d", "1");
704
        }
705
        return(result);
706
    }
707
    
708
    public MetacatClient getMetacatClient() {
709
        return(metacatClient);
710
    }
711
    
712
    //*** BEGIN: Static utility methods ***
713
    
714
    public static String[] parseFileInfo(String fileName) {
715
        String[]                        result = new String[2];
716
        int                             idx;
717
        String                          formatType;
718
        
719
        //*** Set the file format (just using file extension for now).
720
        idx = fileName.lastIndexOf(".");
721
        if (idx > 1)
722
            formatType = fileName.substring(idx+1).toUpperCase();
723
        else
724
            formatType = "";
725
        
726
        result[ClientView.FORMAT_TYPE] = formatType;
727
        result[ClientView.FILE_NAME] = fileName.toString();
728
        return(result);
729
    }
730
    
731
    public static void updateNodeText(Node root, XPath xPath, String expression, String text) {
732
        Node                    targetNode;
733
        
734
        if (text != null && !text.equals("")) {
735
            try {
736
                targetNode = (Node) xPath.evaluate(expression, root, XPathConstants.NODE);
737
                targetNode.setTextContent(text);
738
            } catch (XPathExpressionException ex) {
739
                ex.printStackTrace();
740
            }
741
        }
742
    }
743
    
744
    
745
    public static Node getNode(XPath xPath, String expression, Node root) {
746
        Node                        result = null;
747
        
748
        try {
749
            result = (Node) xPath.evaluate(expression, root, XPathConstants.NODE);
750
        } catch (XPathExpressionException ex) {
751
            ex.printStackTrace();
752
        }
753
        return(result);
754
        
755
    }
756
    
757
    public static String getNodeText(XPath xPath, String expression, Node root) {
758
        Node                        node;
759
        String                      result = null;
760
        
761
        node = getNode(xPath, expression, root);
762
        if (node != null && !node.equals(""))
763
            result = node.getTextContent();
764
        return(result);
765
    }
766
    
767
    public static String[] getNodeTextList(XPath xPath, String expression, Node root) {
768
        NodeList                    nodes;
769
        String                      result[] = null;
770
        int                         size;
771
        
772
        try {
773
            nodes = (NodeList) xPath.evaluate(expression, root, XPathConstants.NODESET);
774
            if (nodes != null && (size = nodes.getLength()) > 0) {
775
                result = new String[size];
776
                for(int i = 0; i < size; i++)
777
                    result[i] = nodes.item(i).getTextContent();
778
            }
779
        } catch (XPathExpressionException ex) {
780
            ex.printStackTrace();
781
        }
782
        return(result);
783
    }
784
    
785
    public static String getStringFromInputStream(InputStream input) {
786
        StringBuffer result = new StringBuffer();
787
        BufferedReader in = new BufferedReader(new InputStreamReader(input));
788
        String line;
789
        try {
790
            while ((line = in.readLine()) != null) {
791
                result.append(line);
792
            }
793
        } catch (IOException e) {
794
            System.out.println("ClientViewHelper.getStringFromInputStream: " + e);
795
        }
796
        return result.toString();
797
    }
798
    
799
    //*** END: Static utility methods ***
800
    
801
    public String makeRedirectUrl() {
802
        String                      result, docId;
803
        
804
        docId = clientViewBean.getMetaFileDocId();
805
        if (clientViewBean.getAction().equals(DOWNLOAD_ACTION)) {
806
            result = null;
807
        } else if (docId != null && !docId.equals("")) {
808
            result = "metacat?action=read&qformat=" +clientViewBean.getQformat()
809
            + "&docid=" + docId
810
                    + "&sessionid=" + clientViewBean.getSessionid();
811
            result += "&msg=" + clientViewBean.getMessage(ClientView.UPDATE_MESSAGE);
812
        } else {
813
            result = "style/common/confirm.jspx";
814
        }
815
        //*** Reset bean action property.
816
        clientViewBean.setAction("");
817
        return(result);
818
    }
819
    
820
    private void download(ClientView bean, HttpServletResponse response) {
821
        Properties                      args;
822
        InputStream                     inStream;
823
        String                          docId, metaId, fNm = null, pth, txtLst[];
824
        String                          msg = "File '~' (~) downloaded";
825
        Node                            branchRoot, metaRoot;
826
        ByteArrayOutputStream           outStream;
827
        int                             intMe;
828
        
829
        docId = bean.getDocId();
830
        metaId = bean.getMetaFileDocId();
831
        if (docId != null && metaId != null && !docId.equals("") && !metaId.equals("")) {
832
            //*** Properties args: key=param_value, value=param_name.
833
            args = new Properties();
834
            args.put("read", "action");
835
            try {
836
                //*** First, retrieve the metadata and get the original filename.
837
                //*** Also, if this is the metadata, get a list of docId's for the package.
838
                setMetadataDoc(metaId);
839
                metaRoot = getMetadataDoc().getDocumentElement();
840
                if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
841
                    //*** FGDC
842
                    if (docId.equals(metaId)) { //*** This is the metadata file.
843
                        pth = ClientFgdcHelper.FGDC_DOCID_ROOT_XPATH.replaceFirst("%1s", docId);
844
                        branchRoot = getNode(xpath, pth, getMetadataDoc());
845
                        fNm = getNodeText(xpath, ClientFgdcHelper.FGDC_FILE_NAME_XPATH, branchRoot);
846
                        fNm = toZipFileName(fNm);
847
                        response.setContentType("application/zip");
848
                        //*** Get the list of docId's for the entire package.
849
                        args.put(metaId, "docid");
850
                        txtLst = getNodeTextList(xpath, ClientFgdcHelper.FGDC_DATA_FILE_NODES_XPATH, branchRoot);
851
                        for (int i = 0; i < txtLst.length; i++)
852
                            args.put(txtLst[i], "docid");
853
                        args.put("zip", "qformat");
854
                    } else { //*** This is a data file.
855
                        pth = ClientFgdcHelper.PATH4ANCESTOR.replaceFirst("%1s", docId);
856
                        pth = pth.replaceFirst("%2s", "digform");
857
                        branchRoot = getNode(xpath, pth, getMetadataDoc());
858
                        fNm = getNodeText(xpath, ClientFgdcHelper.FGDC_DATA_FILE_NAME_XPATH, branchRoot);
859
                        response.setContentType("application/octet-stream");
860
                        args.put(docId, "docid");
861
                        args.put("xml", "qformat");
862
                    }
863
                    System.out.println("ClientViewHelper.download: docId = " + docId + "  metaId= " + metaId + "\npth = " + pth + "\nfNm = " + fNm);
864
                } else {
865
                    //*** TODO: EML -  this is just some basic code to start with.
866
                    if (docId.equals(metaId)) {
867
                        fNm = "emlMetadata.xml";
868
                        txtLst = new String[] {docId};
869
                        args.put(txtLst[0], "docid");
870
                        args.put("zip", "qformat");
871
                        response.setContentType("application/zip");
872
                    } else {
873
                        fNm = "emlData.dat";
874
                        args.put("xml", "qformat");
875
                        args.put(docId, "docid");
876
                        response.setContentType("application/octet-stream");
877
                    }
878
                }
879
                
880
                //*** Set the filename in the response.
881
                response.setHeader("Content-Disposition", "attachment; filename=" + fNm);
882
                
883
                //*** Next, read the file from metacat.
884
                inStream = metacatClient.sendParameters(args);
885
                
886
                //*** Then, convert the input stream into an output stream.
887
                outStream = new ByteArrayOutputStream();
888
                while ((intMe = inStream.read()) != -1) {
889
                    outStream.write(intMe);
890
                }
891
                
892
                //*** Now, write the output stream to the response.
893
                response.setContentLength(outStream.size());
894
                outStream.writeTo(response.getOutputStream());
895
                response.flushBuffer();
896
                
897
                //*** Finally, set the message for the user interface to display.
898
                msg = msg.replaceFirst("~", fNm);
899
                msg = msg.replaceFirst("~", docId);
900
                bean.setMessage(ClientView.SELECT_MESSAGE, msg);
901
            } catch (Exception ex) {
902
                ex.printStackTrace();
903
                bean.setMessage(ClientView.SELECT_MESSAGE, ex.getMessage());
904
            }
905
        }
906
    }
907
    
908
    public static String toZipFileName(String fileName) {
909
        String                      result = "metacat";
910
        int                         idx;
911
        
912
        if (fileName != null && !fileName.equals("") && !fileName.equals(".")) {
913
            idx = fileName.indexOf('.');
914
            if (idx > -1)
915
                result = fileName.substring(0, idx);
916
            else
917
                result = fileName;
918
        }
919
        result += ".zip";
920
        return(result);
921
    }
922
}
(5-5/5)