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

    
17
import edu.ucsb.nceas.metacat.DocInfoHandler;
18
import edu.ucsb.nceas.metacat.IdentifierManager;
19
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
20
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlException;
21
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlForSingleFile;
22
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlInterface;
23
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlList;
24
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessAccess;
25
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
26
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
27
import edu.ucsb.nceas.metacat.client.MetacatClient;
28
import edu.ucsb.nceas.metacat.client.MetacatException;
29
import edu.ucsb.nceas.metacat.client.MetacatFactory;
30
import edu.ucsb.nceas.metacat.client.MetacatInaccessibleException;
31
import edu.ucsb.nceas.metacat.properties.PropertyService;
32
import edu.ucsb.nceas.metacat.service.SessionService;
33
import edu.ucsb.nceas.metacat.shared.AccessException;
34
import edu.ucsb.nceas.metacat.util.DocumentUtil;
35
import edu.ucsb.nceas.metacat.util.SessionData;
36
import edu.ucsb.nceas.utilities.XMLUtilities;
37
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
38
import java.io.BufferedReader;
39
import java.io.ByteArrayOutputStream;
40
import java.io.IOException;
41
import java.io.InputStream;
42
import java.io.InputStreamReader;
43
import java.io.Reader;
44
import java.io.StringReader;
45
import java.util.HashMap;
46
import java.util.Iterator;
47
import java.util.Properties;
48
import java.util.Stack;
49
import java.util.TreeMap;
50
import java.util.Vector;
51
import javax.servlet.http.Cookie;
52
import javax.servlet.http.HttpServletRequest;
53
import javax.servlet.http.HttpServletResponse;
54
import javax.servlet.http.HttpSession;
55
import javax.xml.xpath.XPath;
56
import javax.xml.xpath.XPathConstants;
57
import javax.xml.xpath.XPathExpressionException;
58
import javax.xml.xpath.XPathFactory;
59
import org.w3c.dom.DOMException;
60
import org.w3c.dom.Document;
61
import org.w3c.dom.Node;
62
import org.w3c.dom.NodeList;
63
import org.w3c.dom.Text;
64
import org.xml.sax.ContentHandler;
65
import org.xml.sax.ErrorHandler;
66
import org.xml.sax.InputSource;
67
import org.xml.sax.SAXException;
68
import org.xml.sax.XMLReader;
69
import org.xml.sax.helpers.XMLReaderFactory;
70

    
71
/**
72
 *
73
 * @author barteau
74
 */
75
public class ClientViewHelper {
76
    private XPath                                       xpath = XPathFactory.newInstance().newXPath();
77
    private HttpSession                                 clientSession;
78
    private ClientView                                  clientViewBean = null;
79
    private MetacatClient                               metacatClient = null;
80
    private boolean                                     loggedIn = false;
81
    private Document                                    metadataDoc = null;
82
    private int                                         sizeLimit;
83
    private String                                      contactName = "";
84
    
85
    private static final int DEFAULTFILESIZE = -1;
86
    private static final String                         LDAP_TEMPLATE = "uid=%1s,o=%2s,dc=ecoinformatics,dc=org";
87
    
88
    public static final String                          DOWNLOAD_ACTION = "Download";
89
    
90
    public static final String                          PERMISSION_TYPE_ALLOW = "allow";
91
    
92
    public static final String                          PERMISSION_TYPE_DISALLOW = "deny";
93
    
94
    /**
95
     * Creates a new instance of ClientViewHelper, using info in an HttpServletRequest
96
     * for initializing.
97
     * @param request HttpServletRequest, sent from the client browser.
98
     * @throws edu.ucsb.nceas.metacat.client.MetacatInaccessibleException Thrown
99
     */
100
    public ClientViewHelper(HttpServletRequest request) throws MetacatInaccessibleException {
101
        String                              host, context;
102
        
103
        clientSession = request.getSession(false);
104
        host = request.getHeader("host");
105
        context = request.getContextPath();
106
        init(host, context);
107
    }
108
    
109
    /**
110
     * Creates a new instance of ClientViewHelper, using parameter values
111
     * for initializing.  This constructor is plain java code so it's the portal of
112
     * choice for JUnit testing.
113
     * @param host The host with port (if needed), such as "localhost:8084".
114
     * @param context The application root context.
115
     * @param bean ClientView instance, with pre-populated values.
116
     * @throws edu.ucsb.nceas.metacat.client.MetacatInaccessibleException thrown
117
     */
118
    public ClientViewHelper(String host, String context, ClientView bean) throws MetacatInaccessibleException {
119
        clientViewBean = bean;
120
        init(host, context);
121
    }
122
    
123
    private void init(String host, String context) throws MetacatInaccessibleException {
124
        String                              metacatPath = "http://%1s%2s/metacat";
125
        String                              tmp;
126
        
127
        tmp = metacatPath.replaceFirst("%1s", host);
128
        metacatPath = tmp.replaceFirst("%2s", context);
129
        metacatClient = (MetacatClient) MetacatFactory.createMetacatConnection(metacatPath);
130
        try {
131
        	sizeLimit = 
132
        		(new Integer(PropertyService.getProperty("replication.datafilesizelimit"))).intValue();
133
        } catch (PropertyNotFoundException pnfe) {
134
        	throw new MetacatInaccessibleException(pnfe.getMessage());
135
        }
136
    }
137
    
138
    /**
139
     * Main web API method for handling various actions.
140
     * @param request HttpServletRequest
141
     * @param response HttpServletResponse
142
     * @return String message
143
     */
144
    public String clientRequest(HttpServletRequest request, HttpServletResponse response)  {
145
        String                              result = null, action, contentType;
146
        MultipartParser                     multipartParser;
147
        HashMap<String, Object>             responseMap;
148
        
149
        getMetacatClient().setSessionId(request.getSession().getId());
150
        
151
        if (clientViewBean == null) {
152
            clientViewBean = (ClientView) clientSession.getAttribute(ClientView.CLIENT_VIEW_BEAN);
153
            
154
            if (clientViewBean == null) {
155
            	//make a new one and shove it in the session
156
            	clientViewBean = new ClientView();
157
            	clientSession.setAttribute(ClientView.CLIENT_VIEW_BEAN, clientViewBean);
158
            }
159
        }
160
        
161
        if (clientViewBean != null) {
162
            action = clientViewBean.getAction();
163
            contentType = request.getContentType();
164
            clientViewBean.setSessionid(request.getSession().getId());
165
            //*** BEGIN: manual bind params to bean (if we arrived here via the ClientViewHelper.jspx).
166
            if (action == null || action.equals("")) {
167
                if (contentType != null && contentType.indexOf("multipart/form-data") > -1) {
168
                    action = "Upload";
169
                } else {
170
                    action = request.getParameter("action");
171
                    clientViewBean.setDocId(request.getParameter("docid"));
172
                    clientViewBean.setMetaFileDocId(request.getParameter("metadataDocId"));
173
                    clientViewBean.setQformat(request.getParameter("qformat"));
174
                    clientViewBean.setPublicAccess(request.getParameter("publicAccess") != null);
175
                    clientViewBean.setContentStandard(request.getParameter("contentStandard"));
176
                }
177
                clientViewBean.setAction(action);
178
            }
179
            //*** END: manual bind params to bean.
180
            
181
            if (action != null) {
182
                if (action.equals("Login")) {
183
                    responseMap = handleClientRequest(null);
184
                    //*** Now that the action has been processed, clear it.
185
                    clientViewBean.setAction("");
186
                    if (isLoggedIn()) {
187
//                    	HttpSession session = request.getSession(false);                 	
188
//                    	session.setAttribute("ClientViewHelper", this);
189
                    	Cookie jSessionCookie = new Cookie("JSESSIONID", clientViewBean.getSessionid());
190
                    	response.addCookie(jSessionCookie);
191
                    }
192
                } else if (action.equals("Logout")) {
193
                    responseMap = handleClientRequest(null);
194
                    clientViewBean.setAction("");
195
                } else if (action.equals("Upload")) {
196
                    try {
197
                        //*** Init the MultipartParser.
198
                        multipartParser = new MultipartParser(request, sizeLimit * 1024 * 1024);
199
                        responseMap = handleClientRequest(multipartParser);
200
                    } catch (IOException ex) {
201
                        responseMap = new HashMap<String, Object>();
202
                        responseMap.put("message", ex.getMessage());
203
                    }
204
                    clientViewBean.setAction("");
205
                } else if (action.equals("Download")) {
206
                    responseMap = handleClientRequest(null);
207
                    try {
208
                        handleDownloadResponse(responseMap, response);
209
                    } catch (IOException ex) {
210
                        responseMap = new HashMap<String, Object>();
211
                        responseMap.put("message", ex.getMessage());
212
                    }
213
                    
214
                } else if (action.equals("Set Access")) {
215
                    responseMap = handleClientRequest(null);
216
                    clientViewBean.setAction("");
217
                } else {
218
                    responseMap = handleClientRequest(null);
219
                }
220
                result = (String) responseMap.get("message");
221
            }
222
        } else {
223
            result = "ClientViewHelper.clientRequest: ClientView bean is not instantiated.";
224
        }
225
        return(result);
226
    }
227
    
228
    /**
229
     * Main method for handling various actions.
230
     *
231
     * Note: This is mostly plain java code so it is JUnit friendly
232
     * (pass null as the MulipartParser).
233
     *
234
     * @param multipartParser Only needed if the action is "Upload".
235
     * @return HashMap containing "message", and possibly several other values.  If
236
     * the action is Download, than this will contain all needed values
237
     * to pass to handleDownloadResponse.
238
     */
239
    public HashMap<String, Object> handleClientRequest(MultipartParser multipartParser)  {
240
        String                              result = "", serverResponse;
241
        String                              posted_ldapUserName, tmp, action;
242
        HashMap<String, Object>             responseMap = new HashMap<String, Object>();
243
        
244
        
245
        if (clientViewBean != null) {
246
            action = clientViewBean.getAction();
247
            if (action != null) {
248
                try {
249
                    if (action.equals("Login")) {
250
                        tmp = LDAP_TEMPLATE.replaceFirst("%1s", clientViewBean.getUsername());
251
                        posted_ldapUserName = tmp.replaceFirst("%2s", clientViewBean.getOrganization());
252
                        
253
//                        if (metacatSessionId != null) {
254
//                        	metacatClient.setSessionId(metacatSessionId);
255
//                        }                       
256
                        serverResponse = metacatClient.login(posted_ldapUserName, clientViewBean.getPassword());
257
                        setLoggedIn(serverResponse);
258
                        result = parseXml("message", serverResponse);
259
                        contactName = parseXml("name", serverResponse);
260
                        clientViewBean.setMessage(ClientView.LOGIN_MESSAGE, result);
261
                        clientViewBean.setMessage(ClientView.UPLOAD_MESSAGE, "");
262
                        if (isLoggedIn()) {
263
                            clientViewBean.setSessionid(metacatClient.getSessionId());
264
                            
265
                        }
266
                    } else if (action.equals("Logout")) {
267
                        result = metacatClient.logout();
268
                        setLoggedIn(result);
269
                        result = parseXml("message", result);
270
                        clientViewBean.setMessage(ClientView.LOGIN_MESSAGE, result);
271
                        clientViewBean.setMessage(ClientView.UPLOAD_MESSAGE, "");
272
                        if (!isLoggedIn()) {
273
                            clientViewBean.setUsername("");
274
                            clientViewBean.setPassword("");
275
                            clientViewBean.setOrganization("");
276
                            clientViewBean.setSessionid(null);
277
                        }
278
                    } else if (action.equals("Delete")) {
279
                        ClientFgdcHelper.clientDeleteRequest(clientViewBean, this);
280
                        clientViewBean.setAction("read"); //*** Set for re-query.
281
                        //*** Note: the clientViewBean will already have the updated Meta Doc Id.
282
                        
283
                    } else if (action.equals("Upload")) {
284
                        //*** Only process request if logged in.
285
                        if (isLoggedIn()) {
286
                            if (multipartParser == null)
287
                                result = "ClientViewHelper.handleClientRequest: MultipartParser is not instantiated.";
288
                            else
289
                                result = handlePackageUpload(clientViewBean, multipartParser);
290
                        } else {
291
                            result = "You must be logged in to perform an upload.";
292
                        }
293
                        clientViewBean.setMessage(ClientView.UPLOAD_MESSAGE, result);
294
                    } else if (action.equals("Update")) {
295
                        result = "This is not implemented here.  Call ClientViewHelper.jspx";
296
                    } else if (action.equals("Scope")) {
297
                        result = handleDocIdSelect();
298
                        clientViewBean.setMessage(ClientView.SELECT_MESSAGE, result);
299
                    } else if (action.equals("Download")) {
300
                        responseMap = download(clientViewBean);
301
                    } else if (action.equals("Set Access")) {
302
                        result = handleChangeAccess(clientViewBean.getMetaFileDocId(),
303
                                (clientViewBean.isPublicAccess()? PERMISSION_TYPE_ALLOW: PERMISSION_TYPE_DISALLOW));
304
                        clientViewBean.setMessage(ClientView.UPDATE_MESSAGE, result);
305
                    } else {
306
                        result = action + " action not recognized.";
307
                    }
308
                } catch (Exception ex) {
309
                    result = ex.getMessage();
310
                    clientViewBean.setMessage(ClientView.ERROR_MESSAGE, result);
311
                    ex.printStackTrace();
312
                }
313
            }
314
        } else {
315
            result = "ClientViewHelper.clientRequest: ClientView bean is not instantiated.";
316
        }
317
        responseMap.put("message", result);
318
        return(responseMap);
319
    }
320
    
321
    /**
322
     * This is a convenience method to reduce the amount of code in a Metacat Client.
323
     * It handles creating/reusing (per session) an instance of a ClientViewHelper.
324
     * @param request Since this is intended to be used by an Http client, it is passed the
325
     * available "request" variable (the HttpServletRequest).
326
     * @throws edu.ucsb.nceas.metacat.client.MetacatInaccessibleException Received by MetacatFactory.
327
     * @return ClientViewHelper instance.
328
     */
329
    public static ClientViewHelper clientViewHelperInstance(HttpServletRequest request) {
330
        ClientViewHelper result;
331
        
332
        String sessionId = request.getSession(false).getId();
333
        
334
        result = (ClientViewHelper) request.getSession().getAttribute("ClientViewHelper");
335
        if (result == null) {
336
            try {
337
                result = new ClientViewHelper(request);
338
                request.getSession().setAttribute("ClientViewHelper", result);
339
            } catch (MetacatInaccessibleException ex) {
340
                ex.printStackTrace();
341
            }
342
        }
343
        
344
        if (result.clientViewBean == null) {
345
        	result.clientViewBean = (ClientView) request.getSession().getAttribute(ClientView.CLIENT_VIEW_BEAN);
346
            
347
            if (result.clientViewBean == null) {
348
            	//make a new one and shove it in the session
349
            	result.clientViewBean = new ClientView();
350
            	request.getSession().setAttribute(ClientView.CLIENT_VIEW_BEAN, result.clientViewBean);
351
            }
352
        }
353
        
354
        boolean oldLoginValue = result.loggedIn;
355
        result.setLoggedIn(SessionService.getInstance().validateSession(sessionId));
356
        if (result.isLoggedIn()) {
357
        	SessionData sessionData = SessionService.getInstance().getRegisteredSession(sessionId);
358
        	result.setUserName(sessionData.getName());
359
        }
360
        
361
        if (!oldLoginValue || result.loggedIn) {
362
        	result.clientViewBean.setMessage(ClientView.UPLOAD_MESSAGE, "");
363
        }
364
        
365
        return(result);
366
    }
367
    
368
    /**
369
     * A convenience method to be used by client code that requires
370
     * the user to be logged in.  NOTE: setUser() must have been called first,
371
     * otherwise it will always return false.
372
     * @return boolean  true if user has logged in for this session, false otherwise.
373
     */
374
    public boolean isLoggedIn() {
375
        return(loggedIn);
376
    }
377
    
378
    /**
379
     * After calling "login(ldapUserName, pwd)", call this with the username
380
     * and servers response message.  You can than use isLoggedIn() to determine if
381
     * the user is logged in, getLoginResponseElement(), etc.  The user name will also
382
     * used by calls to doMetadataUpload() for Document Id creation (scope).
383
     * @param userName User name
384
     * @param serverResponse XML login response sent from Metacat.
385
     */
386
    public void setLoggedIn(String serverResponse) {
387
        loggedIn = (serverResponse != null && serverResponse.indexOf("login") > -1);
388
    }
389
    
390
    public void setLoggedIn(boolean isLoggedIn) {
391
        this.loggedIn = isLoggedIn;
392
    }
393
    
394
    public void setUserName(String userName) {
395
        clientViewBean.setUsername(userName);
396
    }
397
    
398
    public String parseXml(String elementName, String xml) {
399
        String                      result = null;
400
        Document                    doc;
401
        
402
        try {
403
            doc = XMLUtilities.getXMLReaderAsDOMDocument(new StringReader(xml));
404
            result = (String) xpath.evaluate(elementName, doc.getDocumentElement(), XPathConstants.STRING);
405
            if (result != null)
406
                result = result.trim();
407
        } catch (IOException ex) {
408
            ex.printStackTrace();
409
        } catch (XPathExpressionException ex) {
410
            ex.printStackTrace();
411
        }
412
        return(result);
413
    }
414
    
415
    public String handleDocIdSelect() {
416
        String                              result = "";
417
        TreeMap                             allDocIds;
418
        
419
        if (!clientViewBean.getPathValue().equals("")) {
420
            allDocIds = getSelectQueryMap();
421
            result = ClientHtmlHelper.mapToHtmlSelect(allDocIds, "docId", "width: 240", 10);
422
        }
423
        return(result);
424
    }
425
    
426
    /**
427
     * Handles metadata file and data file uploads for inserting new
428
     * Metacat data packages.  Note: if content type is not "multipart/form-data",
429
     * nothing will happen.
430
     * @param request HTTP request.
431
     * @return A 1-line status message for the user.
432
     */
433
    public String handlePackageUpload(ClientView clientViewBean, MultipartParser multipartParser) throws Exception {
434
        String                      result = "", contentType, formatType;
435
        String                      lastDocId, nextDocId, metaDocId, metaFileName;
436
        String                      fileInfo[];
437
        Reader                      reader;
438
        int                         sizeLimit, idx;
439
        InputStream                 inputStream;
440
        HashMap                     paramsMap, dataDocIDs;
441
        StringBuffer                fileName;
442
        boolean                     sendIt;
443
        Iterator                    iterIt;
444
        Stack                       docIdStack;
445
        
446
        //*** Get the First file, which should be the metadata file.
447
        paramsMap = new HashMap();
448
        fileName = new StringBuffer();
449
        inputStream = getNextInputStream(multipartParser, fileName, paramsMap);
450
        metaFileName = fileName.toString();
451
        if (metaFileName.toLowerCase().endsWith(".xml")) {
452
            //*** Keep it here for updating.
453
            setMetadataDoc(inputStream);
454
            //*** Get the Metadata File's DOC ID.
455
            String scope = clientViewBean.getUsername();
456
            scope = scope.replaceAll(" ", "_");
457
            scope = scope.toLowerCase();
458
            lastDocId = getMetacatClient().getLastDocid(scope);
459
            metaDocId = lastDocId = nextDocId(lastDocId, scope);
460
            
461
            //*** Loop thru all of the data files, get fileName and inputStream.
462
            dataDocIDs = new HashMap();
463
            fileName = new StringBuffer();
464
            while ((inputStream = getNextInputStream(multipartParser, fileName, paramsMap)) != null) {
465
                //*** Get the data file's DOC ID.
466
                nextDocId = nextDocId(lastDocId, scope);
467
                
468
                fileInfo = parseFileInfo(fileName.toString());
469
                dataDocIDs.put(nextDocId, fileInfo);
470
                
471
                //*** Upload the data file to metacat.
472
                getMetacatClient().upload(nextDocId, fileName.toString(), inputStream, DEFAULTFILESIZE);
473
                
474
                lastDocId = nextDocId;
475
                fileName = new StringBuffer();
476
            }
477
            
478
            if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
479
                sendIt = ClientFgdcHelper.handlePackageUpload(metaDocId, dataDocIDs, contactName, metaFileName, getMetadataDoc());
480
            } else {
481
                //TODO add other types of metadata grammars here...
482
                System.out.println("ClientViewHelper.handlePackageUpload: not an FGDC file = " + fileName);
483
                result = fileName + " is not an FGDC file.  Files not uploaded.";
484
                sendIt = false;
485
            }
486
            
487
            if (sendIt) {
488
                //*** Upload the metadata file to metacat.
489
                reader = XMLUtilities.getDOMTreeAsReader(metadataDoc.getDocumentElement(), false);
490
                getMetacatClient().insert(metaDocId, reader, null);
491
                
492
                result = "MetaCat Package Inserted:  the Document Identifier is " + metaDocId;
493
                reader.close();
494
                //*** Grant the public read access to the meta file.
495
                if (paramsMap.containsKey("publicAccess")) {
496
                    docIdStack = new Stack();
497
                    docIdStack.addAll(dataDocIDs.keySet());
498
                    setPublicAccess(this.PERMISSION_TYPE_ALLOW, metaDocId, docIdStack);
499
                }
500
            }
501
        } else {
502
            result = "The first file must be an XML Metadata file.  Files not uploaded.";
503
        }
504
        if (inputStream != null)
505
            inputStream.close();
506
        return(result);
507
    }
508
    
509
    private String setPublicAccess(String permissionType, String metaDocId, Stack docIdStack)
510
    throws InsufficientKarmaException, MetacatException, MetacatInaccessibleException, AccessControlException, McdbDocNotFoundException{
511
        String                      result = " for Documents ";
512
        String                      docId, lst = metaDocId, permOrder;
513
        
514
        /*if (permissionType.equals("allow"))
515
            permOrder = "denyFirst";
516
        else
517
            permOrder = "allowFirst";
518
        permOrder = "allowFirst";
519
        
520
        getMetacatClient().setAccess(metaDocId, "public", "read", permissionType, permOrder);*/
521
        setPublicReadAccess(permissionType, metaDocId) ;
522
        //*** Grant the public read access to the data files.
523
        while(!docIdStack.isEmpty()) {
524
            docId = (String) docIdStack.pop();
525
            //getMetacatClient().setAccess(docId, "public", "read", permissionType, permOrder);
526
            setPublicReadAccess(permissionType, docId);
527
            lst += ", " + docId;
528
        }
529
        result = "Changed public read access to '" + permissionType + "' for " + result + lst;
530
        return(result);
531
    }
532
    
533
    /*
534
     * Set up public access by using accessblock to replace old success rules.
535
     * First, we need to get original access rules.
536
     * Second, remove all access rules of the user public, then add the new rules. 
537
     */
538
    private void setPublicReadAccess(String permissionType, String docid) 
539
        throws InsufficientKarmaException, MetacatException, MetacatInaccessibleException, AccessControlException, McdbDocNotFoundException{
540
      String originalAccessBlock = getMetacatClient().getAccessControl(docid);
541
      Vector<XMLAccessDAO> accessList = parseAccessXMLBlock(docid, originalAccessBlock);
542
      if(accessList != null  && !accessList.isEmpty()) {
543
        //there are some access rules in the metacat server for this docid
544
        XMLAccessDAO rule = accessList.elementAt(0);
545
        //we should persist the perm order from original access block
546
        String permOrder = rule.getPermOrder();
547
        //remove all public access rule but preserver other access rules.
548
        removeAllPublicAccessRules(accessList);
549
        //generate a new access rule and add it to the list
550
        XMLAccessDAO newRule = generateXMLAccessDAO(docid, AccessControlInterface.PUBLIC,
551
            AccessControlInterface.READSTRING, permissionType, permOrder);
552
        accessList.add(newRule);
553
      } else {
554
        //generate a new access rule and add it to the list
555
        accessList = new Vector<XMLAccessDAO>();
556
        XMLAccessDAO newRule = generateXMLAccessDAO(docid, AccessControlInterface.PUBLIC,
557
            AccessControlInterface.READSTRING, permissionType, AccessControlInterface.ALLOWFIRST);
558
        accessList.add(newRule);
559
      }
560
      //transform the new XMLAccessDAO object list to the String 
561
      AccessControlForSingleFile controller = new AccessControlForSingleFile(docid);
562
      String accessBlock = controller.getAccessString(accessList);
563
      //send the access block to the metacat
564
      getMetacatClient().setAccess(docid, accessBlock);
565
    }
566
    
567
    /*
568
     * Parse the access xml block to get access rule list object.
569
     */
570
    private Vector<XMLAccessDAO> parseAccessXMLBlock(String docId, String accessXMLBlock) throws AccessControlException{
571
      try { 
572
        // use DocInfoHandler to parse the access section into DAO objects
573
        XMLReader parser = null;
574
        DocInfoHandler docInfoHandler = new DocInfoHandler(docId); 
575
        ContentHandler chandler = docInfoHandler;
576

    
577
        // Get an instance of the parser
578
        String parserName = PropertyService.getProperty("xml.saxparser");
579
        parser = XMLReaderFactory.createXMLReader(parserName);
580

    
581
        // Turn off validation
582
        parser.setFeature("http://xml.org/sax/features/validation", false);
583
        parser.setContentHandler((ContentHandler)chandler);
584
        parser.setErrorHandler((ErrorHandler)chandler);
585

    
586
        parser.parse(new InputSource(new StringReader(accessXMLBlock)));
587
        
588
        XMLAccessAccess xmlAccessAccess = new XMLAccessAccess();
589
         Vector<XMLAccessDAO> accessRuleList = docInfoHandler.getAccessControlList();
590
         return accessRuleList;
591
           
592

    
593
      } catch (PropertyNotFoundException pnfe) {
594
        throw new AccessControlException("ClientViewHelper.parseAccessXMLBlock - "
595
            + "property error when replacing permissions: " + pnfe.getMessage());
596
      } catch (AccessException ae) {
597
        throw new AccessControlException("ClientViewHelper.parseAccessXMLBlock - "
598
            + "DB access error when replacing permissions: " + ae.getMessage());
599
      } catch (SAXException se) {
600
        throw new AccessControlException("ClientViewHelper.parseAccessXMLBlock - "
601
            + "SAX error when replacing permissions: " + se.getMessage());
602
      } catch(IOException ioe) {
603
        throw new AccessControlException("ClientViewHelper.parseAccessXMLBlock - "
604
            + "I/O error when replacing permissions: " + ioe.getMessage());
605
      }
606
    }
607
    
608
    /*
609
     * Populate xmlAccessDAO object with the some parameters.
610
     */
611
    private XMLAccessDAO generateXMLAccessDAO(String docid, String principalName,
612
        String permission, String permType, String permOrder) throws McdbDocNotFoundException {
613
      String localId = DocumentUtil.getDocIdFromString(docid);
614
      int rev = DocumentUtil.getRevisionFromAccessionNumber(docid);
615
      String identifier = IdentifierManager.getInstance().getGUID(localId, rev);
616
      XMLAccessDAO xmlAccessDAO = new XMLAccessDAO();
617
      xmlAccessDAO.setGuid(identifier);
618
      xmlAccessDAO.setPrincipalName(principalName);
619
      xmlAccessDAO.setPermission(Integer.valueOf(AccessControlList.intValue(permission)).longValue());
620
      xmlAccessDAO.setPermType(permType);
621
      xmlAccessDAO.setPermOrder(permOrder);
622
      return xmlAccessDAO;
623
    }
624
    
625
    
626
    /*
627
     * Remove every access rule for user public from the specified access rule list
628
     */
629
    private void removeAllPublicAccessRules(Vector<XMLAccessDAO> accessList) {
630
      if(accessList != null && !accessList.isEmpty()) {
631
        Vector<Integer> removingIndexList = new Vector<Integer>();
632
        for(int i=0; i<accessList.size(); i++) {
633
          XMLAccessDAO rule = accessList.elementAt(i);
634
          if(rule != null && rule.getPrincipalName() != null && rule.getPrincipalName().equalsIgnoreCase(AccessControlInterface.PUBLIC)) {
635
            //store the index which should be remove
636
            removingIndexList.add(new Integer(i));
637
          }      
638
        }
639
        if(!removingIndexList.isEmpty()) {
640
          for(int i=removingIndexList.size()-1; i>=0; i--) {
641
            accessList.remove(removingIndexList.elementAt(i).intValue());
642
          }
643
       }
644
      }
645
    }
646
    
647
    private String handleChangeAccess(String metaDocId, String permissionType) throws Exception {
648
        Stack                       dataDocIDs;
649
        String                      result = "", xpathExpr = null;
650
        
651
        setMetadataDoc(metaDocId);
652
        //*** Build list of sub-documents.
653
        if (clientViewBean.getContentStandard().equals(ClientView.FEDERAL_GEOGRAPHIC_DATA_COMMITTEE)) {
654
            xpathExpr = ClientFgdcHelper.SUB_DOCS_PATH;
655
        } else if (clientViewBean.getContentStandard().equals(ClientView.ECOLOGICAL_METADATA_LANGUAGE)) {
656
            xpathExpr = null; //TODO  - EML
657
        }
658
        if (xpathExpr != null) {
659
            dataDocIDs = getNodeTextStack(xpath, xpathExpr, getMetadataDoc().getDocumentElement());
660
            result = setPublicAccess(permissionType, metaDocId, dataDocIDs);
661
        }
662
        return(result);
663
    }
664
    
665
    public String handleFileUpdate(MultipartParser multipartParser) throws Exception {
666
        String                      result = "", fNm, action, lastDocId, newDocId, xPathQuery, qFrmt;
667
        InputStream                 inputStream;
668
        HashMap                     paramsMap;
669
        StringBuffer                fileName;
670
        Iterator                    iterIt;
671
        boolean                     sendIt;
672
        String                      metadataDocId, fileInfo[];
673
        
674
        paramsMap = new HashMap();
675
        fileName = new StringBuffer();
676
        if ((inputStream = getNextInputStream(multipartParser, fileName, paramsMap)) != null) {
677
            action = (String) paramsMap.get("action");
678
            //*** Get the Doc Id.
679
            lastDocId = (String) paramsMap.get("docid");
680
            
681
            //*** Get the metadata Doc Id.
682
            metadataDocId = (String) paramsMap.get("metadataDocId");
683
            clientViewBean.setMetaFileDocId(metadataDocId);
684
            
685
            //*** Get the qformat.
686
            qFrmt = (String) paramsMap.get("qformat");
687
            clientViewBean.setQformat(qFrmt);
688
            
689
            fNm = fileName.toString();
690
            
691
            try {
692
                if (lastDocId.equals(metadataDocId)) { //*** This is the metadata file.
693
                    //*** Keep it here for updating.
694
                    setMetadataDoc(inputStream);
695
                    if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
696
                        clientViewBean.setContentStandard(ClientView.FEDERAL_GEOGRAPHIC_DATA_COMMITTEE);
697
                        if (!ClientFgdcHelper.hasMetacatInfo(lastDocId, getMetadataDoc())) {
698
                            
699
                            //*** Save the Doc Id for re-query.
700
                            clientViewBean.setMetaFileDocId(lastDocId);
701
                            clientViewBean.setAction("read"); //*** Set for re-query.
702
                            result = "Update not performed: the Metadata file has no prior Metacat info in it.";
703
                        } else {
704
                            xPathQuery = ClientFgdcHelper.XPATH_QUERY_TEMPLATE.replaceFirst("%1s", lastDocId);
705
                            newDocId = updateMetadataDoc(lastDocId, xPathQuery, fNm);
706
                            
707
                            //*** Save the Doc Id for re-query.
708
                            clientViewBean.setMetaFileDocId(newDocId);
709
                            clientViewBean.setAction("read"); //*** Set for re-query.
710
                            result = "Updated to new document (from " + lastDocId + " to " + newDocId + ")";
711
                        }
712
                    } else {
713
                        //***TODO This is EML.
714
                        clientViewBean.setContentStandard(ClientView.ECOLOGICAL_METADATA_LANGUAGE);
715
                        
716
                        //*** Save the Doc Id for re-query.
717
                        clientViewBean.setMetaFileDocId(lastDocId);
718
                        clientViewBean.setAction("read"); //*** Set for re-query.
719
                        result = "Currently this functionality only supports FGDC metadata.";
720
                    }
721
                } else {
722
                    //*** This is a data file.
723
                    //*** Query for the metadata, we need to update it with the new data file doc id.
724
                    setMetadataDoc(metadataDocId);
725
                    
726
                    if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
727
                        clientViewBean.setContentStandard(ClientView.FEDERAL_GEOGRAPHIC_DATA_COMMITTEE);
728
                        fileInfo = parseFileInfo(fNm);
729
                        
730
                        xPathQuery = ClientFgdcHelper.FGDC_DATA_FILE_QUERY_XPATH.replaceFirst("%1s", lastDocId);
731
                        newDocId = nextVersion(lastDocId, xPathQuery);
732
                        ClientFgdcHelper.updateFileNameAndType(getMetadataDoc().getDocumentElement(), newDocId, fileInfo);
733
                        //*** Upload the data file to metacat.
734
                        getMetacatClient().upload(newDocId, fNm, inputStream, DEFAULTFILESIZE);
735
                        result = "Updated to new document (from " + lastDocId + " to " + newDocId + ")";
736
                        
737
                        //*** Upload the metadata file to metacat.
738
                        xPathQuery = ClientFgdcHelper.XPATH_QUERY_TEMPLATE.replaceFirst("%1s", metadataDocId);
739
                        newDocId = updateMetadataDoc(metadataDocId, xPathQuery, null);
740
                        
741
                        //*** Save the new meta Doc Id for re-query.
742
                        clientViewBean.setMetaFileDocId(newDocId);
743
                        clientViewBean.setAction("read"); //*** Set for re-query.
744
                        
745
                    } else {
746
                        //***TODO This is EML.
747
                        clientViewBean.setContentStandard(ClientView.ECOLOGICAL_METADATA_LANGUAGE);
748
                        
749
                        //*** Save the old meta Doc Id for re-query.
750
                        clientViewBean.setMetaFileDocId(metadataDocId);
751
                        clientViewBean.setAction("read"); //*** Set for re-query.
752
                        result = "Currently this functionality only supports FGDC metadata.";
753
                    }
754
                }
755
            } catch (java.io.IOException ex) {
756
                ex.printStackTrace();
757
            }
758
        } else {
759
            result = "Please enter the updated file path/name.";
760
        }
761
        clientViewBean.setMessage(ClientView.UPDATE_MESSAGE, result);
762
        return(result);
763
    }
764
    
765
    private String updateMetadataDoc(String lastDocId, String docIdPath, String origFileName) {
766
        String                      newDocId = null;
767
        Reader                      reader;
768
        
769
        //*** Update the metadata with the new Doc Id version.
770
        try {
771
            newDocId = nextVersion(lastDocId, docIdPath);
772
            if (origFileName != null) {
773
                if (clientViewBean.getContentStandard().equals(ClientView.FEDERAL_GEOGRAPHIC_DATA_COMMITTEE))
774
                    ClientFgdcHelper.updateMetadataFileName(getMetadataDoc().getDocumentElement(), newDocId, origFileName);
775
                else
776
                    ; //TODO EML, etc.
777
            }
778
            //*** Upload the metadata file to metacat.
779
            reader = XMLUtilities.getDOMTreeAsReader(getMetadataDoc().getDocumentElement(), false);
780
            getMetacatClient().update(newDocId, reader, null);
781
            reader.close();
782
        } catch (Exception ex) {
783
            ex.printStackTrace();
784
        }
785
        return(newDocId);
786
    }
787
    
788
    private InputStream getNextInputStream(MultipartParser multipartParser, StringBuffer fileName, HashMap paramsMap)
789
    throws IOException {
790
        InputStream                     result = null;
791
        Part                            part;
792
        String                          parmName = null, value = null, fnam;
793
        
794
        while ((part = multipartParser.readNextPart()) != null) {
795
            if (part.isParam()) {
796
                parmName = part.getName();
797
                value = ((ParamPart) part).getStringValue();
798
                paramsMap.put(parmName, value);
799
                
800
            } else if (part.isFile()) {
801
                fnam = ((FilePart) part).getFileName();
802
                if (fnam != null && !fnam.equals("")) {
803
                    //*** File name is passed back via StringBuffer fileName param.
804
                    fileName.append(fnam);
805
                    result = ((FilePart) part).getInputStream();
806
                    break;
807
                }
808
            }
809
        }
810
        return(result);
811
    }
812
    
813
    private void getRemainingParameters(MultipartParser multipartParser, HashMap paramsMap)
814
    throws IOException {
815
        InputStream                     result = null;
816
        Part                            part;
817
        String                          parmName = null, value = null, fnam;
818
        
819
        while ((part = multipartParser.readNextPart()) != null) {
820
            if (part.isParam()) {
821
                parmName = part.getName();
822
                value = ((ParamPart) part).getStringValue();
823
                paramsMap.put(parmName, value);
824
            }
825
        }
826
    }
827
    
828
    /**
829
     * Queries Metacat for document listings, and returns the results in a TreeMap,
830
     * where the key is the Doc Id, and the value is the Create Date.  If the document
831
     * contains the specified 'returnfield', an addtional entry will be created with
832
     * the value being a Vector of sub-DocId's.  The key of this entry will be the
833
     * original DocId with some addtional text added.
834
     * Reads bean properties 'pathExpr' (String[]), 'pathValue' (String)
835
     * and 'returnfield' (String).
836
     * @return TreeMap
837
     */
838
    public TreeMap getSelectQueryMap() {
839
        TreeMap                         result;
840
        Document                        doc;
841
        NodeList                        nodeLst, subNodeLst;
842
        Node                            node, subNode;
843
        String                          key, val, paramExpr, paramVal;
844
        String                          value, returnFld;
845
        String                          path;
846
        Vector                          optGroup;
847
        final String                    DOCID_EXPR = "./docid";
848
        final String                    DOCNAME_EXPR = "./createdate";
849
        final String                    PARAM_EXPR = "./param[@name='%1s']";
850
        
851
        path = clientViewBean.getPathExpr();
852
        returnFld = clientViewBean.getReturnfield();
853
        value = clientViewBean.getPathValue();
854
        
855
        result = new TreeMap();
856
        //paramExpr = String.format(PARAM_EXPR, returnFld);
857
        paramExpr = PARAM_EXPR.replaceFirst("%1s", returnFld);
858
        //*** Query the database ***
859
        doc = query(path, value, returnFld);
860
        //*** Build the TreeMap to return ***
861
        try {
862
            nodeLst = (NodeList) xpath.evaluate("/resultset/document", doc, XPathConstants.NODESET);
863
            for (int i = 0; i < nodeLst.getLength(); i++) {
864
                node = nodeLst.item(i);
865
                key = xpath.evaluate(DOCID_EXPR, node);
866
                val = xpath.evaluate(DOCNAME_EXPR, node);
867
                result.put(key, key + " (" + val + ")");
868
                
869
                //*** returnfield values ***
870
                subNodeLst = (NodeList) xpath.evaluate(paramExpr, node, XPathConstants.NODESET);
871
                if (subNodeLst.getLength() > 0) {
872
                    optGroup = new Vector();
873
                    for (int k = 0; k < subNodeLst.getLength(); k++) {
874
                        subNode =  subNodeLst.item(k);
875
                        paramVal = xpath.evaluate("text()", subNode);
876
                        optGroup.add(paramVal);
877
                    }
878
                    result.put(key + " Data Files", optGroup);
879
                }
880
                
881
            }
882
        } catch (XPathExpressionException ex) {
883
            ex.printStackTrace();
884
        }
885
        return(result);
886
    }
887
    
888
    /**
889
     * Query metacat for documents that 'CONTAINS' the value at the specified XPath
890
     * expression.  Additionally, returns another non-standard field value.
891
     * Standard info contains: DocId, DocName, DocType, CreateDate, and UpdateDate.
892
     * @param pathExpr String contianing an XPath expression.
893
     * @param pathValue String containing a comparison value at the XPath expression.
894
     * @param returnFld String containing an XPath expression to a field which will be returned
895
     * in addition to the standard info.
896
     * @return DOM Document containing the results.
897
     */
898
    public Document query(String pathExpr, String pathValue, String returnFld) {
899
        Document                        result = null;
900
        InputStream                     response;
901
        BufferedReader                  buffy;
902
        Properties                      prop;
903
        
904
        try {
905
            prop = new Properties();
906
            prop.put("action", "query");
907
            prop.put("qformat", "xml");
908
            prop.put(pathExpr, pathValue);
909
            if (returnFld != null) {
910
                prop.put("returnfield", returnFld);
911
            }
912
            
913
            response = metacatClient.sendParameters(prop);
914
            if (response != null) {
915
                buffy = new BufferedReader(new InputStreamReader(response));
916
                result = XMLUtilities.getXMLReaderAsDOMDocument(buffy);
917
            }
918
        } catch (IOException ex) {
919
            ex.printStackTrace();
920
        } catch (Exception ex) {
921
            ex.printStackTrace();
922
        }
923
        return(result);
924
    }
925
    
926
    public void setMetadataDoc(Document doc) {
927
        metadataDoc = doc;
928
    }
929
    
930
    public void setMetadataDoc(String docId) throws Exception {
931
        Document                        doc = null;
932
        BufferedReader                  buffy;
933
        InputStream                     response;
934

    
935
        response = metacatClient.read(docId);
936
        if (response != null) {
937
            buffy = new BufferedReader(new InputStreamReader(response));
938
            doc = XMLUtilities.getXMLReaderAsDOMDocument(buffy);
939
            response.close();
940
        }
941
        setMetadataDoc(doc);
942
    }
943
    
944
    public void setMetadataDoc(InputStream ioStream) throws IOException {
945
        BufferedReader                          buffy;
946
        
947
        if (ioStream != null) {
948
            buffy = new BufferedReader(new InputStreamReader(ioStream));
949
            metadataDoc = XMLUtilities.getXMLReaderAsDOMDocument(buffy);
950
        }
951
    }
952
    
953
    public Document getMetadataDoc() {
954
        return(metadataDoc);
955
    }
956
    
957
    public String nextVersion(String lastDocId, String xPathQuery) throws XPathExpressionException {
958
        String                      result = null, tokens[], scope, ready2Split, tmp;
959
        int                         vers, docNum;
960
        final int                   LAST_TOKEN = 2;
961
        final String                TEMPLATE = "%1s.%2d.%3d";
962
        Node                        node;
963
        
964
        //*** Parse the last Doc Id, and increment the version number.
965
        if(lastDocId != null && lastDocId.indexOf(".") > -1) {
966
            ready2Split = lastDocId.replace('.','~'); //*** This is necessary for the split to work.
967
            tokens = ready2Split.split("~");
968
            if(tokens.length > LAST_TOKEN && !tokens[LAST_TOKEN].equals("")) {
969
                scope = tokens[LAST_TOKEN - 2];
970
                docNum = Integer.parseInt(tokens[LAST_TOKEN - 1]);
971
                try {
972
                    vers = Integer.parseInt(tokens[LAST_TOKEN]);
973
                    //result = String.format(TEMPLATE, scope, docNum, 1 + vers);
974
                    tmp = TEMPLATE.replaceFirst("%1s", scope);
975
                    tmp = tmp.replaceFirst("%2d", String.valueOf(docNum));
976
                    result = tmp.replaceFirst("%3d", String.valueOf(vers + 1));
977
                    
978
                } catch (NumberFormatException ex) {
979
                    //*** In case the lastDocId has something other than a number.
980
                    //result = String.format(TEMPLATE, scope, docNum, 1);
981
                    tmp = TEMPLATE.replaceFirst("%1s", scope);
982
                    tmp = tmp.replaceFirst("%2d", String.valueOf(docNum));
983
                    result = tmp.replaceFirst("%3d", "1");
984
                }
985
            } else {
986
                //*** In case the lastDocId ends with a '.'
987
                result = lastDocId + "1";
988
            }
989
        } else {
990
            //*** In case of missing doc Id.
991
            result = null;
992
        }
993
        //*** Update the Doc Id in the metadata file.
994
        if (getMetadataDoc() != null) {
995
            node = (Node) xpath.evaluate(xPathQuery, getMetadataDoc().getDocumentElement(), XPathConstants.NODE);
996
            setTextContent(xpath, node, result);
997
        }
998
        return(result);
999
    }
1000
    
1001
    private String nextDocId(String lastDocId, String scope) {
1002
        String                      result = null, tokens[], tmp;
1003
        int                         vers;
1004
        String                      template = scope.toLowerCase() + ".%1d.%2d";
1005
        
1006
        if(lastDocId != null && lastDocId.indexOf(".") > -1) {
1007
            lastDocId = lastDocId.replace('.','~'); //*** This is necessary for the split to work.
1008
            tokens = lastDocId.split("~");
1009
            if(tokens.length > 1 && !tokens[1].equals("")) {
1010
                try {
1011
                    vers = Integer.parseInt(tokens[1]);
1012
                    //result = String.format(template, 1 + vers, 1);
1013
                    tmp = template.replaceFirst("%1d", String.valueOf(1 + vers));
1014
                    result = tmp.replaceFirst("%2d", "1");
1015
                } catch (NumberFormatException ex) {
1016
                    //*** In case the lastDocId has something other than a number.
1017
                    //result = String.format(template, 1, 1);
1018
                    tmp = template.replaceFirst("%1d", "1");
1019
                    result = tmp.replaceFirst("%2d", "1");
1020
                }
1021
            } else {
1022
                //*** In case the lastDocId ends with a '.'
1023
                //result = String.format(template, 1, 1);
1024
                tmp = template.replaceFirst("%1d", "1");
1025
                result = tmp.replaceFirst("%2d", "1");
1026
            }
1027
        } else {
1028
            //*** In case there isn't any doc Id's with the user name.
1029
            //result = String.format(template, 1, 1);
1030
            tmp = template.replaceFirst("%1d", "1");
1031
            result = tmp.replaceFirst("%2d", "1");
1032
        }
1033
        return(result);
1034
    }
1035
    
1036
    public MetacatClient getMetacatClient() {
1037
        return(metacatClient);
1038
    }
1039
    
1040
    //*** BEGIN: Static utility methods ***
1041
    
1042
    public static String[] parseFileInfo(String fileName) {
1043
        String[]                        result = new String[2];
1044
        int                             idx;
1045
        String                          formatType;
1046
        
1047
        //*** Set the file format (just using file extension for now).
1048
        idx = fileName.lastIndexOf(".");
1049
        if (idx > 1)
1050
            formatType = fileName.substring(idx+1).toUpperCase();
1051
        else
1052
            formatType = "";
1053
        
1054
        result[ClientView.FORMAT_TYPE] = formatType;
1055
        result[ClientView.FILE_NAME] = fileName.toString();
1056
        return(result);
1057
    }
1058
    
1059
    public static void updateNodeText(Node root, XPath xPath, String expression, String text) {
1060
        Node                    targetNode;
1061
        
1062
        if (text != null && !text.equals("")) {
1063
            try {
1064
                targetNode = (Node) xPath.evaluate(expression, root, XPathConstants.NODE);
1065
                setTextContent(xPath, targetNode, text);
1066
                //targetNode.setTextContent(text);
1067
            } catch (XPathExpressionException ex) {
1068
                ex.printStackTrace();
1069
            }
1070
        }
1071
    }
1072
    
1073
    
1074
    public static Node getNode(XPath xPath, String expression, Node root) {
1075
        Node                        result = null;
1076
        
1077
        try {
1078
            result = (Node) xPath.evaluate(expression, root, XPathConstants.NODE);
1079
        } catch (XPathExpressionException ex) {
1080
            ex.printStackTrace();
1081
        }
1082
        return(result);
1083
        
1084
    }
1085
    
1086
    public static String getNodeText(XPath xPath, String expression, Node root) {
1087
        Node                        node;
1088
        String                      result = null;
1089
        
1090
        node = getNode(xPath, expression, root);
1091
        if (node != null && !node.equals(""))
1092
            result = getTextContent(xPath, node);
1093
        //result = node.getTextContent(); Not in java 1.4
1094
        return(result);
1095
    }
1096
    
1097
    public static String[] getNodeTextList(XPath xPath, String expression, Node root) {
1098
        NodeList                    nodes;
1099
        String                      result[] = new String[0];
1100
        int                         size;
1101
        
1102
        try {
1103
            nodes = (NodeList) xPath.evaluate(expression, root, XPathConstants.NODESET);
1104
            if (nodes != null && (size = nodes.getLength()) > 0) {
1105
                result = new String[size];
1106
                for(int i = 0; i < size; i++)
1107
                    result[i] = getTextContent(xPath, nodes.item(i));
1108
                //result[i] = nodes.item(i).getTextContent(); Not in java 1.4
1109
            }
1110
        } catch (XPathExpressionException ex) {
1111
            ex.printStackTrace();
1112
        }
1113
        return(result);
1114
    }
1115
    
1116
    public static Stack getNodeTextStack(XPath xpathInstance, String xpathExpr, Node parentNode) {
1117
        String                      nodeLst[];
1118
        Stack                       result = new Stack();
1119
        
1120
        nodeLst = getNodeTextList(xpathInstance, xpathExpr, parentNode);
1121
        for(int i = 0; i < nodeLst.length; i++)
1122
            result.push(nodeLst[i]);
1123
        return(result);
1124
    }
1125
    
1126
    public static String getStringFromInputStream(InputStream input) {
1127
        StringBuffer result = new StringBuffer();
1128
        BufferedReader in = new BufferedReader(new InputStreamReader(input));
1129
        String line;
1130
        try {
1131
            while ((line = in.readLine()) != null) {
1132
                result.append(line);
1133
            }
1134
        } catch (IOException e) {
1135
            System.out.println("ClientViewHelper.getStringFromInputStream: " + e);
1136
        }
1137
        return result.toString();
1138
    }
1139
    
1140
    //*** END: Static utility methods ***
1141
    
1142
    public String makeRedirectUrl() {
1143
        String                      result, docId, message;
1144
        
1145
        docId = clientViewBean.getMetaFileDocId();
1146
        //System.out.println("get the the session id "+clientViewBean.getSessionid()+ " from the client view bean object "+clientViewBean.toString());
1147
        if (clientViewBean.getAction().equals(DOWNLOAD_ACTION)) {
1148
            result = null;
1149
        } else if (docId != null && !docId.equals("")) {
1150
            message = clientViewBean.getMessage(ClientView.UPDATE_MESSAGE);
1151
            result = "metacat?action=read&qformat=" +clientViewBean.getQformat()
1152
            + "&docid=" + docId + "&sessionid=" + clientViewBean.getSessionid() + "&message=" + message;
1153
        } else {
1154
            result = "style/skins/" + clientViewBean.getQformat() + "/confirm.jsp";
1155
        }
1156
        //*** Reset bean action property.
1157
        clientViewBean.setAction("");
1158
        return(result);
1159
    }
1160
    
1161
    private HashMap<String, Object> download(ClientView bean) {
1162
        Properties                      args;
1163
        InputStream                     inStream;
1164
        String                          docId, metaId, fNm = null, pth, txtLst[];
1165
        String                          msg = "File '~' (~) downloaded";
1166
        Node                            branchRoot, metaRoot;
1167
        ByteArrayOutputStream           outStream;
1168
        int                             intMe;
1169
        HashMap<String, Object>         responseMap = new HashMap<String, Object>();
1170
        
1171
        docId = bean.getDocId();
1172
        metaId = bean.getMetaFileDocId();
1173
        if (docId != null && metaId != null && !docId.equals("") && !metaId.equals("")) {
1174
            //*** Properties args: key=param_value, value=param_name.
1175
            args = new Properties();
1176
            args.put("read", "action");
1177
            try {
1178
                //*** First, retrieve the metadata and get the original filename.
1179
                //*** Also, if this is the metadata, get a list of docId's for the package.
1180
                setMetadataDoc(metaId);
1181
                metaRoot = getMetadataDoc().getDocumentElement();
1182
                if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
1183
                    //*** FGDC
1184
                    if (docId.equals(metaId)) { //*** This is the metadata file.
1185
                        pth = ClientFgdcHelper.FGDC_DOCID_ROOT_XPATH.replaceFirst("%1s", docId);
1186
                        branchRoot = getNode(xpath, pth, getMetadataDoc());
1187
                        fNm = getNodeText(xpath, ClientFgdcHelper.FGDC_FILE_NAME_XPATH, branchRoot);
1188
                        //include the filename for the docid
1189
                        args.put(fNm, docId);
1190
                        fNm = toZipFileName(fNm);
1191
                        responseMap.put("contentType", "application/zip");
1192
                        //*** Get the list of docId's for the entire package.
1193
                        args.put(metaId, "docid");
1194
                        txtLst = getNodeTextList(xpath, ClientFgdcHelper.FGDC_DATA_FILE_NODES_XPATH, branchRoot);
1195
                        for (int i = 0; i < txtLst.length; i++) {
1196
                        	String additionalDocId = txtLst[i];
1197
                        	if (additionalDocId != null && additionalDocId.length() > 1) {
1198
                        		//look up the filename from the metadata
1199
                        		String tempPath = ClientFgdcHelper.PATH4ANCESTOR.replaceFirst("%1s", additionalDocId);
1200
                        		tempPath = tempPath.replaceFirst("%2s", "digform");
1201
                                Node tempBranchRoot = getNode(xpath, tempPath, getMetadataDoc());
1202
                                String tempFileName = getNodeText(xpath, ClientFgdcHelper.FGDC_DATA_FILE_NAME_XPATH, tempBranchRoot);
1203
                                //include the docid
1204
                        		args.put(additionalDocId, "docid");
1205
                        		//include the filename for the docid
1206
                        		args.put(tempFileName, additionalDocId);
1207
                        	}
1208
                        }
1209
                        args.put("zip", "qformat");
1210
                    } else { //*** This is a data file.
1211
                        pth = ClientFgdcHelper.PATH4ANCESTOR.replaceFirst("%1s", docId);
1212
                        pth = pth.replaceFirst("%2s", "digform");
1213
                        branchRoot = getNode(xpath, pth, getMetadataDoc());
1214
                        fNm = getNodeText(xpath, ClientFgdcHelper.FGDC_DATA_FILE_NAME_XPATH, branchRoot);
1215
                        responseMap.put("contentType", "application/octet-stream");
1216
                        args.put(docId, "docid");
1217
                        args.put("xml", "qformat");
1218
                    }
1219
                } else {
1220
                    //*** TODO: EML -  this is just some basic code to start with.
1221
                    if (docId.equals(metaId)) {
1222
                        fNm = "emlMetadata.xml";
1223
                        txtLst = new String[] {docId};
1224
                        args.put(txtLst[0], "docid");
1225
                        args.put("zip", "qformat");
1226
                        responseMap.put("contentType", "application/zip");
1227
                    } else {
1228
                        fNm = "emlData.dat";
1229
                        args.put("xml", "qformat");
1230
                        args.put(docId, "docid");
1231
                        responseMap.put("contentType", "application/octet-stream");
1232
                    }
1233
                }
1234
                
1235
                //*** Set the filename in the response.
1236
                responseMap.put("Content-Disposition", "attachment; filename=" + fNm);
1237
                
1238
                //*** Next, read the file from metacat.
1239
                inStream = metacatClient.sendParameters(args);
1240
                
1241
                //*** Then, convert the input stream into an output stream.
1242
                outStream = new ByteArrayOutputStream();
1243
                while ((intMe = inStream.read()) != -1) {
1244
                    outStream.write(intMe);
1245
                }
1246
                
1247
                //*** Now, write the output stream to the response.
1248
                responseMap.put("outputStream", outStream);
1249
                
1250
                //*** Finally, set the message for the user interface to display.
1251
                msg = msg.replaceFirst("~", fNm);
1252
                msg = msg.replaceFirst("~", docId);
1253
                bean.setMessage(ClientView.SELECT_MESSAGE, msg);
1254
            } catch (Exception ex) {
1255
                ex.printStackTrace();
1256
                bean.setMessage(ClientView.SELECT_MESSAGE, ex.getMessage());
1257
            }
1258
        }
1259
        responseMap.put("message", bean.getMessage(ClientView.SELECT_MESSAGE));
1260
        return(responseMap);
1261
    }
1262
    
1263
    private void handleDownloadResponse(HashMap responseMap, HttpServletResponse response) throws IOException {
1264
        ByteArrayOutputStream                       outStream;
1265
        String                                      contentDisposition, contentType;
1266
        
1267
        contentType = (String) responseMap.get("contentType");
1268
        contentDisposition = (String) responseMap.get("Content-Disposition");
1269
        outStream = (ByteArrayOutputStream) responseMap.get("outputStream");
1270
        
1271
        response.setContentType(contentType);
1272
        response.setHeader("Content-Disposition", contentDisposition);
1273
        response.setContentLength(outStream.size());
1274
        outStream.writeTo(response.getOutputStream());
1275
        response.flushBuffer();
1276
    }
1277
    
1278
    public static String toZipFileName(String fileName) {
1279
        String                      result = "metacat";
1280
        int                         idx;
1281
        
1282
        if (fileName != null && !fileName.equals("") && !fileName.equals(".")) {
1283
            idx = fileName.indexOf('.');
1284
            if (idx > -1)
1285
                result = fileName.substring(0, idx);
1286
            else
1287
                result = fileName;
1288
        }
1289
        result += ".zip";
1290
        return(result);
1291
    }
1292
    
1293
    public static void setTextContent(XPath xPath, Node elementNode, String content) throws DOMException {
1294
        Text                        textNode, newTxtNode;
1295
        Document                    document;
1296
        
1297
        textNode = (Text) getNode(xPath, "text()", elementNode);
1298
        if (textNode != null) {
1299
            if (isElementContentWhitespace(textNode)) {
1300
                //*** If there is an existing text node, and it's whitespace,
1301
                //*** create a new text node and insert it before whitespace.
1302
                document = elementNode.getOwnerDocument();
1303
                newTxtNode = document.createTextNode(content);
1304
                elementNode.insertBefore(newTxtNode, textNode);
1305
            } else {
1306
                //*** If there is an existing text node, and it has content,
1307
                //*** overwrite the existing text.
1308
                textNode.setNodeValue(content);
1309
            }
1310
        } else {
1311
            //*** If there isn't an existing text node,
1312
            //*** create a new text node and append it to the elementNode.
1313
            document = elementNode.getOwnerDocument();
1314
            newTxtNode = document.createTextNode(content);
1315
            elementNode.appendChild(newTxtNode);
1316
        }
1317
    }
1318
    
1319
    public static String getTextContent(XPath xPath, Node elementNode) throws DOMException {
1320
        String                      result = "";
1321
        Text                        textNode;
1322
        
1323
        if (elementNode.getNodeType() != Node.TEXT_NODE)
1324
            textNode = (Text) getNode(xPath, "text()", elementNode);
1325
        else
1326
            textNode = (Text) elementNode;
1327
        if (textNode != null)
1328
            result = textNode.getNodeValue();
1329
        return(result);
1330
    }
1331
    
1332
    public static boolean isElementContentWhitespace(Text textNode) {
1333
        boolean                     result = false;
1334
        String                      val;
1335
        
1336
        if ((val = textNode.getNodeValue()) != null) {
1337
            if (val != null) {
1338
                val = val.trim();
1339
                result = (val.length() == 0);
1340
            }
1341
        }
1342
        return(result);
1343
    }
1344
    
1345
}
(5-5/5)