Project

General

Profile

1 3319 barteau
/*
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 6728 tao
17 6744 leinfelder
import edu.ucsb.nceas.metacat.IdentifierManager;
18
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
19 6728 tao
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlException;
20
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlForSingleFile;
21
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlList;
22
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessAccess;
23 3517 barteau
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
24 3319 barteau
import edu.ucsb.nceas.metacat.client.MetacatClient;
25 3517 barteau
import edu.ucsb.nceas.metacat.client.MetacatException;
26 3319 barteau
import edu.ucsb.nceas.metacat.client.MetacatFactory;
27
import edu.ucsb.nceas.metacat.client.MetacatInaccessibleException;
28 5030 daigle
import edu.ucsb.nceas.metacat.properties.PropertyService;
29 5071 daigle
import edu.ucsb.nceas.metacat.service.SessionService;
30 6728 tao
import edu.ucsb.nceas.metacat.shared.AccessException;
31
import edu.ucsb.nceas.metacat.util.DocumentUtil;
32 5071 daigle
import edu.ucsb.nceas.metacat.util.SessionData;
33 3319 barteau
import edu.ucsb.nceas.utilities.XMLUtilities;
34 4080 daigle
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
35 7475 leinfelder
import edu.ucsb.nceas.utilities.access.AccessControlInterface;
36
import edu.ucsb.nceas.utilities.access.DocInfoHandler;
37
import edu.ucsb.nceas.utilities.access.XMLAccessDAO;
38
39 3319 barteau
import java.io.BufferedReader;
40 3483 barteau
import java.io.ByteArrayOutputStream;
41 3319 barteau
import java.io.IOException;
42
import java.io.InputStream;
43
import java.io.InputStreamReader;
44
import java.io.Reader;
45
import java.io.StringReader;
46
import java.util.HashMap;
47 3364 barteau
import java.util.Iterator;
48 3319 barteau
import java.util.Properties;
49 3517 barteau
import java.util.Stack;
50 3319 barteau
import java.util.TreeMap;
51
import java.util.Vector;
52 5071 daigle
import javax.servlet.http.Cookie;
53 3319 barteau
import javax.servlet.http.HttpServletRequest;
54
import javax.servlet.http.HttpServletResponse;
55
import javax.servlet.http.HttpSession;
56
import javax.xml.xpath.XPath;
57
import javax.xml.xpath.XPathConstants;
58
import javax.xml.xpath.XPathExpressionException;
59
import javax.xml.xpath.XPathFactory;
60 3539 barteau
import org.w3c.dom.DOMException;
61 3319 barteau
import org.w3c.dom.Document;
62
import org.w3c.dom.Node;
63
import org.w3c.dom.NodeList;
64 3539 barteau
import org.w3c.dom.Text;
65 6728 tao
import org.xml.sax.ContentHandler;
66
import org.xml.sax.ErrorHandler;
67
import org.xml.sax.InputSource;
68
import org.xml.sax.SAXException;
69
import org.xml.sax.XMLReader;
70
import org.xml.sax.helpers.XMLReaderFactory;
71 3319 barteau
72
/**
73
 *
74
 * @author barteau
75
 */
76
public class ClientViewHelper {
77
    private XPath                                       xpath = XPathFactory.newInstance().newXPath();
78
    private HttpSession                                 clientSession;
79
    private ClientView                                  clientViewBean = null;
80
    private MetacatClient                               metacatClient = null;
81
    private boolean                                     loggedIn = false;
82
    private Document                                    metadataDoc = null;
83
    private int                                         sizeLimit;
84
    private String                                      contactName = "";
85
86 6684 tao
    private static final int DEFAULTFILESIZE = -1;
87 3367 barteau
    private static final String                         LDAP_TEMPLATE = "uid=%1s,o=%2s,dc=ecoinformatics,dc=org";
88 3319 barteau
89 3483 barteau
    public static final String                          DOWNLOAD_ACTION = "Download";
90
91 3517 barteau
    public static final String                          PERMISSION_TYPE_ALLOW = "allow";
92
93
    public static final String                          PERMISSION_TYPE_DISALLOW = "deny";
94
95 3319 barteau
    /**
96 3530 barteau
     * Creates a new instance of ClientViewHelper, using info in an HttpServletRequest
97
     * for initializing.
98
     * @param request HttpServletRequest, sent from the client browser.
99
     * @throws edu.ucsb.nceas.metacat.client.MetacatInaccessibleException Thrown
100 3319 barteau
     */
101
    public ClientViewHelper(HttpServletRequest request) throws MetacatInaccessibleException {
102 3530 barteau
        String                              host, context;
103 3319 barteau
104 5071 daigle
        clientSession = request.getSession(false);
105 3319 barteau
        host = request.getHeader("host");
106
        context = request.getContextPath();
107 3530 barteau
        init(host, context);
108
    }
109
110
    /**
111
     * Creates a new instance of ClientViewHelper, using parameter values
112
     * for initializing.  This constructor is plain java code so it's the portal of
113
     * choice for JUnit testing.
114
     * @param host The host with port (if needed), such as "localhost:8084".
115
     * @param context The application root context.
116
     * @param bean ClientView instance, with pre-populated values.
117
     * @throws edu.ucsb.nceas.metacat.client.MetacatInaccessibleException thrown
118
     */
119
    public ClientViewHelper(String host, String context, ClientView bean) throws MetacatInaccessibleException {
120
        clientViewBean = bean;
121
        init(host, context);
122
    }
123
124
    private void init(String host, String context) throws MetacatInaccessibleException {
125
        String                              metacatPath = "http://%1s%2s/metacat";
126
        String                              tmp;
127
128 3367 barteau
        tmp = metacatPath.replaceFirst("%1s", host);
129
        metacatPath = tmp.replaceFirst("%2s", context);
130 3319 barteau
        metacatClient = (MetacatClient) MetacatFactory.createMetacatConnection(metacatPath);
131 4080 daigle
        try {
132
        	sizeLimit =
133 4306 leinfelder
        		(new Integer(PropertyService.getProperty("replication.datafilesizelimit"))).intValue();
134 4080 daigle
        } catch (PropertyNotFoundException pnfe) {
135
        	throw new MetacatInaccessibleException(pnfe.getMessage());
136
        }
137 3319 barteau
    }
138
139 3530 barteau
    /**
140
     * Main web API method for handling various actions.
141
     * @param request HttpServletRequest
142
     * @param response HttpServletResponse
143
     * @return String message
144
     */
145 3319 barteau
    public String clientRequest(HttpServletRequest request, HttpServletResponse response)  {
146 3530 barteau
        String                              result = null, action, contentType;
147 3319 barteau
        MultipartParser                     multipartParser;
148 6059 leinfelder
        HashMap<String, Object>             responseMap;
149 3319 barteau
150 5071 daigle
        getMetacatClient().setSessionId(request.getSession().getId());
151
152 3741 leinfelder
        if (clientViewBean == null) {
153 3319 barteau
            clientViewBean = (ClientView) clientSession.getAttribute(ClientView.CLIENT_VIEW_BEAN);
154 3741 leinfelder
155
            if (clientViewBean == null) {
156
            	//make a new one and shove it in the session
157
            	clientViewBean = new ClientView();
158
            	clientSession.setAttribute(ClientView.CLIENT_VIEW_BEAN, clientViewBean);
159
            }
160
        }
161 3319 barteau
162
        if (clientViewBean != null) {
163
            action = clientViewBean.getAction();
164
            contentType = request.getContentType();
165 6696 tao
            clientViewBean.setSessionid(request.getSession().getId());
166 3393 barteau
            //*** BEGIN: manual bind params to bean (if we arrived here via the ClientViewHelper.jspx).
167
            if (action == null || action.equals("")) {
168 3539 barteau
                if (contentType != null && contentType.indexOf("multipart/form-data") > -1) {
169 3393 barteau
                    action = "Upload";
170
                } else {
171
                    action = request.getParameter("action");
172 3483 barteau
                    clientViewBean.setDocId(request.getParameter("docid"));
173
                    clientViewBean.setMetaFileDocId(request.getParameter("metadataDocId"));
174
                    clientViewBean.setQformat(request.getParameter("qformat"));
175 3517 barteau
                    clientViewBean.setPublicAccess(request.getParameter("publicAccess") != null);
176
                    clientViewBean.setContentStandard(request.getParameter("contentStandard"));
177 3393 barteau
                }
178 3530 barteau
                clientViewBean.setAction(action);
179 3393 barteau
            }
180 3517 barteau
            //*** END: manual bind params to bean.
181 3502 barteau
182 3486 barteau
            if (action != null) {
183 3530 barteau
                if (action.equals("Login")) {
184
                    responseMap = handleClientRequest(null);
185
                    //*** Now that the action has been processed, clear it.
186
                    clientViewBean.setAction("");
187 5071 daigle
                    if (isLoggedIn()) {
188
//                    	HttpSession session = request.getSession(false);
189
//                    	session.setAttribute("ClientViewHelper", this);
190
                    	Cookie jSessionCookie = new Cookie("JSESSIONID", clientViewBean.getSessionid());
191
                    	response.addCookie(jSessionCookie);
192
                    }
193 3530 barteau
                } else if (action.equals("Logout")) {
194
                    responseMap = handleClientRequest(null);
195
                    clientViewBean.setAction("");
196
                } else if (action.equals("Upload")) {
197
                    try {
198
                        //*** Init the MultipartParser.
199
                        multipartParser = new MultipartParser(request, sizeLimit * 1024 * 1024);
200
                        responseMap = handleClientRequest(multipartParser);
201
                    } catch (IOException ex) {
202 6059 leinfelder
                        responseMap = new HashMap<String, Object>();
203 3530 barteau
                        responseMap.put("message", ex.getMessage());
204
                    }
205
                    clientViewBean.setAction("");
206
                } else if (action.equals("Download")) {
207
                    responseMap = handleClientRequest(null);
208
                    try {
209
                        handleDownloadResponse(responseMap, response);
210
                    } catch (IOException ex) {
211 6059 leinfelder
                        responseMap = new HashMap<String, Object>();
212 3530 barteau
                        responseMap.put("message", ex.getMessage());
213
                    }
214
215
                } else if (action.equals("Set Access")) {
216
                    responseMap = handleClientRequest(null);
217
                    clientViewBean.setAction("");
218
                } else {
219
                    responseMap = handleClientRequest(null);
220
                }
221
                result = (String) responseMap.get("message");
222
            }
223
        } else {
224
            result = "ClientViewHelper.clientRequest: ClientView bean is not instantiated.";
225
        }
226
        return(result);
227
    }
228
229
    /**
230
     * Main method for handling various actions.
231
     *
232
     * Note: This is mostly plain java code so it is JUnit friendly
233
     * (pass null as the MulipartParser).
234
     *
235
     * @param multipartParser Only needed if the action is "Upload".
236
     * @return HashMap containing "message", and possibly several other values.  If
237
     * the action is Download, than this will contain all needed values
238
     * to pass to handleDownloadResponse.
239
     */
240 6059 leinfelder
    public HashMap<String, Object> handleClientRequest(MultipartParser multipartParser)  {
241 3530 barteau
        String                              result = "", serverResponse;
242 5071 daigle
        String                              posted_ldapUserName, tmp, action;
243 6059 leinfelder
        HashMap<String, Object>             responseMap = new HashMap<String, Object>();
244 3530 barteau
245
246
        if (clientViewBean != null) {
247
            action = clientViewBean.getAction();
248
            if (action != null) {
249 3486 barteau
                try {
250
                    if (action.equals("Login")) {
251
                        tmp = LDAP_TEMPLATE.replaceFirst("%1s", clientViewBean.getUsername());
252
                        posted_ldapUserName = tmp.replaceFirst("%2s", clientViewBean.getOrganization());
253
254 5071 daigle
//                        if (metacatSessionId != null) {
255
//                        	metacatClient.setSessionId(metacatSessionId);
256
//                        }
257 3486 barteau
                        serverResponse = metacatClient.login(posted_ldapUserName, clientViewBean.getPassword());
258
                        setLoggedIn(serverResponse);
259 3530 barteau
                        result = parseXml("message", serverResponse);
260 3486 barteau
                        contactName = parseXml("name", serverResponse);
261 3530 barteau
                        clientViewBean.setMessage(ClientView.LOGIN_MESSAGE, result);
262 3486 barteau
                        clientViewBean.setMessage(ClientView.UPLOAD_MESSAGE, "");
263
                        if (isLoggedIn()) {
264
                            clientViewBean.setSessionid(metacatClient.getSessionId());
265 5071 daigle
266 3486 barteau
                        }
267
                    } else if (action.equals("Logout")) {
268 3530 barteau
                        result = metacatClient.logout();
269
                        setLoggedIn(result);
270
                        result = parseXml("message", result);
271
                        clientViewBean.setMessage(ClientView.LOGIN_MESSAGE, result);
272 3486 barteau
                        clientViewBean.setMessage(ClientView.UPLOAD_MESSAGE, "");
273
                        if (!isLoggedIn()) {
274
                            clientViewBean.setUsername("");
275
                            clientViewBean.setPassword("");
276
                            clientViewBean.setOrganization("");
277
                            clientViewBean.setSessionid(null);
278
                        }
279
                    } else if (action.equals("Delete")) {
280
                        ClientFgdcHelper.clientDeleteRequest(clientViewBean, this);
281
                        clientViewBean.setAction("read"); //*** Set for re-query.
282
                        //*** Note: the clientViewBean will already have the updated Meta Doc Id.
283 3530 barteau
284 3486 barteau
                    } else if (action.equals("Upload")) {
285 3530 barteau
                        //*** Only process request if logged in.
286 3486 barteau
                        if (isLoggedIn()) {
287 3530 barteau
                            if (multipartParser == null)
288
                                result = "ClientViewHelper.handleClientRequest: MultipartParser is not instantiated.";
289
                            else
290
                                result = handlePackageUpload(clientViewBean, multipartParser);
291
                        } else {
292
                            result = "You must be logged in to perform an upload.";
293 3486 barteau
                        }
294 3530 barteau
                        clientViewBean.setMessage(ClientView.UPLOAD_MESSAGE, result);
295 3486 barteau
                    } else if (action.equals("Update")) {
296 3530 barteau
                        result = "This is not implemented here.  Call ClientViewHelper.jspx";
297 3486 barteau
                    } else if (action.equals("Scope")) {
298 3530 barteau
                        result = handleDocIdSelect();
299
                        clientViewBean.setMessage(ClientView.SELECT_MESSAGE, result);
300 3486 barteau
                    } else if (action.equals("Download")) {
301 3530 barteau
                        responseMap = download(clientViewBean);
302 3517 barteau
                    } else if (action.equals("Set Access")) {
303 3530 barteau
                        result = handleChangeAccess(clientViewBean.getMetaFileDocId(),
304 3517 barteau
                                (clientViewBean.isPublicAccess()? PERMISSION_TYPE_ALLOW: PERMISSION_TYPE_DISALLOW));
305
                        clientViewBean.setMessage(ClientView.UPDATE_MESSAGE, result);
306 3530 barteau
                    } else {
307
                        result = action + " action not recognized.";
308 3319 barteau
                    }
309 3486 barteau
                } catch (Exception ex) {
310 3530 barteau
                    result = ex.getMessage();
311
                    clientViewBean.setMessage(ClientView.ERROR_MESSAGE, result);
312 3486 barteau
                    ex.printStackTrace();
313 3319 barteau
                }
314
            }
315
        } else {
316 3530 barteau
            result = "ClientViewHelper.clientRequest: ClientView bean is not instantiated.";
317 3319 barteau
        }
318 3530 barteau
        responseMap.put("message", result);
319
        return(responseMap);
320 3319 barteau
    }
321
322
    /**
323
     * This is a convenience method to reduce the amount of code in a Metacat Client.
324
     * It handles creating/reusing (per session) an instance of a ClientViewHelper.
325
     * @param request Since this is intended to be used by an Http client, it is passed the
326
     * available "request" variable (the HttpServletRequest).
327
     * @throws edu.ucsb.nceas.metacat.client.MetacatInaccessibleException Received by MetacatFactory.
328
     * @return ClientViewHelper instance.
329
     */
330
    public static ClientViewHelper clientViewHelperInstance(HttpServletRequest request) {
331 5071 daigle
        ClientViewHelper result;
332 3319 barteau
333 5071 daigle
        String sessionId = request.getSession(false).getId();
334
335 3319 barteau
        result = (ClientViewHelper) request.getSession().getAttribute("ClientViewHelper");
336
        if (result == null) {
337
            try {
338
                result = new ClientViewHelper(request);
339
                request.getSession().setAttribute("ClientViewHelper", result);
340
            } catch (MetacatInaccessibleException ex) {
341
                ex.printStackTrace();
342
            }
343
        }
344
345 5071 daigle
        if (result.clientViewBean == null) {
346
        	result.clientViewBean = (ClientView) request.getSession().getAttribute(ClientView.CLIENT_VIEW_BEAN);
347
348
            if (result.clientViewBean == null) {
349
            	//make a new one and shove it in the session
350
            	result.clientViewBean = new ClientView();
351
            	request.getSession().setAttribute(ClientView.CLIENT_VIEW_BEAN, result.clientViewBean);
352
            }
353
        }
354
355
        boolean oldLoginValue = result.loggedIn;
356 5374 berkley
        result.setLoggedIn(SessionService.getInstance().validateSession(sessionId));
357 5071 daigle
        if (result.isLoggedIn()) {
358 5374 berkley
        	SessionData sessionData = SessionService.getInstance().getRegisteredSession(sessionId);
359 5071 daigle
        	result.setUserName(sessionData.getName());
360
        }
361
362
        if (!oldLoginValue || result.loggedIn) {
363
        	result.clientViewBean.setMessage(ClientView.UPLOAD_MESSAGE, "");
364
        }
365
366 3319 barteau
        return(result);
367
    }
368
369
    /**
370
     * A convenience method to be used by client code that requires
371
     * the user to be logged in.  NOTE: setUser() must have been called first,
372
     * otherwise it will always return false.
373
     * @return boolean  true if user has logged in for this session, false otherwise.
374
     */
375
    public boolean isLoggedIn() {
376
        return(loggedIn);
377
    }
378
379
    /**
380
     * After calling "login(ldapUserName, pwd)", call this with the username
381
     * and servers response message.  You can than use isLoggedIn() to determine if
382
     * the user is logged in, getLoginResponseElement(), etc.  The user name will also
383
     * used by calls to doMetadataUpload() for Document Id creation (scope).
384
     * @param userName User name
385
     * @param serverResponse XML login response sent from Metacat.
386
     */
387
    public void setLoggedIn(String serverResponse) {
388 3539 barteau
        loggedIn = (serverResponse != null && serverResponse.indexOf("login") > -1);
389 3319 barteau
    }
390
391 5071 daigle
    public void setLoggedIn(boolean isLoggedIn) {
392
        this.loggedIn = isLoggedIn;
393
    }
394
395
    public void setUserName(String userName) {
396
        clientViewBean.setUsername(userName);
397
    }
398
399 3364 barteau
    public String parseXml(String elementName, String xml) {
400 3319 barteau
        String                      result = null;
401
        Document                    doc;
402
403
        try {
404
            doc = XMLUtilities.getXMLReaderAsDOMDocument(new StringReader(xml));
405
            result = (String) xpath.evaluate(elementName, doc.getDocumentElement(), XPathConstants.STRING);
406
            if (result != null)
407
                result = result.trim();
408
        } catch (IOException ex) {
409
            ex.printStackTrace();
410
        } catch (XPathExpressionException ex) {
411
            ex.printStackTrace();
412
        }
413
        return(result);
414
    }
415
416 3364 barteau
    public String handleDocIdSelect() {
417 3319 barteau
        String                              result = "";
418
        TreeMap                             allDocIds;
419
420
        if (!clientViewBean.getPathValue().equals("")) {
421
            allDocIds = getSelectQueryMap();
422
            result = ClientHtmlHelper.mapToHtmlSelect(allDocIds, "docId", "width: 240", 10);
423
        }
424
        return(result);
425
    }
426
427
    /**
428
     * Handles metadata file and data file uploads for inserting new
429
     * Metacat data packages.  Note: if content type is not "multipart/form-data",
430
     * nothing will happen.
431
     * @param request HTTP request.
432
     * @return A 1-line status message for the user.
433
     */
434 3364 barteau
    public String handlePackageUpload(ClientView clientViewBean, MultipartParser multipartParser) throws Exception {
435 3319 barteau
        String                      result = "", contentType, formatType;
436 3364 barteau
        String                      lastDocId, nextDocId, metaDocId, metaFileName;
437
        String                      fileInfo[];
438 3319 barteau
        Reader                      reader;
439
        int                         sizeLimit, idx;
440
        InputStream                 inputStream;
441
        HashMap                     paramsMap, dataDocIDs;
442 3486 barteau
        StringBuffer                fileName;
443 3319 barteau
        boolean                     sendIt;
444 3502 barteau
        Iterator                    iterIt;
445 3517 barteau
        Stack                       docIdStack;
446 3319 barteau
447
        //*** Get the First file, which should be the metadata file.
448
        paramsMap = new HashMap();
449 3486 barteau
        fileName = new StringBuffer();
450 3319 barteau
        inputStream = getNextInputStream(multipartParser, fileName, paramsMap);
451 3364 barteau
        metaFileName = fileName.toString();
452
        if (metaFileName.toLowerCase().endsWith(".xml")) {
453 3319 barteau
            //*** Keep it here for updating.
454
            setMetadataDoc(inputStream);
455
            //*** Get the Metadata File's DOC ID.
456 6064 leinfelder
            String scope = clientViewBean.getUsername();
457
            scope = scope.replaceAll(" ", "_");
458
            scope = scope.toLowerCase();
459
            lastDocId = getMetacatClient().getLastDocid(scope);
460
            metaDocId = lastDocId = nextDocId(lastDocId, scope);
461 3319 barteau
462
            //*** Loop thru all of the data files, get fileName and inputStream.
463
            dataDocIDs = new HashMap();
464 3486 barteau
            fileName = new StringBuffer();
465 3319 barteau
            while ((inputStream = getNextInputStream(multipartParser, fileName, paramsMap)) != null) {
466
                //*** Get the data file's DOC ID.
467 6064 leinfelder
                nextDocId = nextDocId(lastDocId, scope);
468 3319 barteau
469 3372 barteau
                fileInfo = parseFileInfo(fileName.toString());
470 3364 barteau
                dataDocIDs.put(nextDocId, fileInfo);
471 3502 barteau
472 3319 barteau
                //*** Upload the data file to metacat.
473 6684 tao
                getMetacatClient().upload(nextDocId, fileName.toString(), inputStream, DEFAULTFILESIZE);
474 3319 barteau
475
                lastDocId = nextDocId;
476 3486 barteau
                fileName = new StringBuffer();
477 3319 barteau
            }
478
479
            if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
480 3364 barteau
                sendIt = ClientFgdcHelper.handlePackageUpload(metaDocId, dataDocIDs, contactName, metaFileName, getMetadataDoc());
481 3319 barteau
            } else {
482
                //TODO add other types of metadata grammars here...
483
                System.out.println("ClientViewHelper.handlePackageUpload: not an FGDC file = " + fileName);
484
                result = fileName + " is not an FGDC file.  Files not uploaded.";
485
                sendIt = false;
486
            }
487
488
            if (sendIt) {
489
                //*** Upload the metadata file to metacat.
490
                reader = XMLUtilities.getDOMTreeAsReader(metadataDoc.getDocumentElement(), false);
491
                getMetacatClient().insert(metaDocId, reader, null);
492
493
                result = "MetaCat Package Inserted:  the Document Identifier is " + metaDocId;
494
                reader.close();
495 3502 barteau
                //*** Grant the public read access to the meta file.
496
                if (paramsMap.containsKey("publicAccess")) {
497 3517 barteau
                    docIdStack = new Stack();
498
                    docIdStack.addAll(dataDocIDs.keySet());
499
                    setPublicAccess(this.PERMISSION_TYPE_ALLOW, metaDocId, docIdStack);
500 3502 barteau
                }
501 3319 barteau
            }
502
        } else {
503
            result = "The first file must be an XML Metadata file.  Files not uploaded.";
504
        }
505
        if (inputStream != null)
506
            inputStream.close();
507
        return(result);
508
    }
509
510 3517 barteau
    private String setPublicAccess(String permissionType, String metaDocId, Stack docIdStack)
511 6744 leinfelder
    throws InsufficientKarmaException, MetacatException, MetacatInaccessibleException, AccessControlException, McdbDocNotFoundException{
512 3517 barteau
        String                      result = " for Documents ";
513
        String                      docId, lst = metaDocId, permOrder;
514
515 6696 tao
        /*if (permissionType.equals("allow"))
516 3517 barteau
            permOrder = "denyFirst";
517
        else
518 6728 tao
            permOrder = "allowFirst";
519 6696 tao
        permOrder = "allowFirst";
520 3517 barteau
521 6728 tao
        getMetacatClient().setAccess(metaDocId, "public", "read", permissionType, permOrder);*/
522
        setPublicReadAccess(permissionType, metaDocId) ;
523 3517 barteau
        //*** Grant the public read access to the data files.
524
        while(!docIdStack.isEmpty()) {
525
            docId = (String) docIdStack.pop();
526 6728 tao
            //getMetacatClient().setAccess(docId, "public", "read", permissionType, permOrder);
527
            setPublicReadAccess(permissionType, docId);
528 3517 barteau
            lst += ", " + docId;
529
        }
530
        result = "Changed public read access to '" + permissionType + "' for " + result + lst;
531
        return(result);
532
    }
533
534 6728 tao
    /*
535
     * Set up public access by using accessblock to replace old success rules.
536
     * First, we need to get original access rules.
537
     * Second, remove all access rules of the user public, then add the new rules.
538
     */
539
    private void setPublicReadAccess(String permissionType, String docid)
540 6744 leinfelder
        throws InsufficientKarmaException, MetacatException, MetacatInaccessibleException, AccessControlException, McdbDocNotFoundException{
541 6728 tao
      String originalAccessBlock = getMetacatClient().getAccessControl(docid);
542
      Vector<XMLAccessDAO> accessList = parseAccessXMLBlock(docid, originalAccessBlock);
543
      if(accessList != null  && !accessList.isEmpty()) {
544
        //there are some access rules in the metacat server for this docid
545
        XMLAccessDAO rule = accessList.elementAt(0);
546
        //we should persist the perm order from original access block
547
        String permOrder = rule.getPermOrder();
548
        //remove all public access rule but preserver other access rules.
549
        removeAllPublicAccessRules(accessList);
550
        //generate a new access rule and add it to the list
551
        XMLAccessDAO newRule = generateXMLAccessDAO(docid, AccessControlInterface.PUBLIC,
552
            AccessControlInterface.READSTRING, permissionType, permOrder);
553
        accessList.add(newRule);
554
      } else {
555
        //generate a new access rule and add it to the list
556
        accessList = new Vector<XMLAccessDAO>();
557
        XMLAccessDAO newRule = generateXMLAccessDAO(docid, AccessControlInterface.PUBLIC,
558
            AccessControlInterface.READSTRING, permissionType, AccessControlInterface.ALLOWFIRST);
559
        accessList.add(newRule);
560
      }
561
      //transform the new XMLAccessDAO object list to the String
562
      AccessControlForSingleFile controller = new AccessControlForSingleFile(docid);
563
      String accessBlock = controller.getAccessString(accessList);
564
      //send the access block to the metacat
565
      getMetacatClient().setAccess(docid, accessBlock);
566
    }
567
568
    /*
569
     * Parse the access xml block to get access rule list object.
570
     */
571
    private Vector<XMLAccessDAO> parseAccessXMLBlock(String docId, String accessXMLBlock) throws AccessControlException{
572
      try {
573
        // use DocInfoHandler to parse the access section into DAO objects
574
        XMLReader parser = null;
575
        DocInfoHandler docInfoHandler = new DocInfoHandler(docId);
576
        ContentHandler chandler = docInfoHandler;
577
578
        // Get an instance of the parser
579
        String parserName = PropertyService.getProperty("xml.saxparser");
580
        parser = XMLReaderFactory.createXMLReader(parserName);
581
582
        // Turn off validation
583
        parser.setFeature("http://xml.org/sax/features/validation", false);
584
        parser.setContentHandler((ContentHandler)chandler);
585
        parser.setErrorHandler((ErrorHandler)chandler);
586
587
        parser.parse(new InputSource(new StringReader(accessXMLBlock)));
588
589
        XMLAccessAccess xmlAccessAccess = new XMLAccessAccess();
590
         Vector<XMLAccessDAO> accessRuleList = docInfoHandler.getAccessControlList();
591
         return accessRuleList;
592
593
594
      } catch (PropertyNotFoundException pnfe) {
595
        throw new AccessControlException("ClientViewHelper.parseAccessXMLBlock - "
596
            + "property error when replacing permissions: " + pnfe.getMessage());
597
      } catch (AccessException ae) {
598
        throw new AccessControlException("ClientViewHelper.parseAccessXMLBlock - "
599
            + "DB access error when replacing permissions: " + ae.getMessage());
600
      } catch (SAXException se) {
601
        throw new AccessControlException("ClientViewHelper.parseAccessXMLBlock - "
602
            + "SAX error when replacing permissions: " + se.getMessage());
603
      } catch(IOException ioe) {
604
        throw new AccessControlException("ClientViewHelper.parseAccessXMLBlock - "
605
            + "I/O error when replacing permissions: " + ioe.getMessage());
606
      }
607
    }
608
609
    /*
610
     * Populate xmlAccessDAO object with the some parameters.
611
     */
612
    private XMLAccessDAO generateXMLAccessDAO(String docid, String principalName,
613 6744 leinfelder
        String permission, String permType, String permOrder) throws McdbDocNotFoundException {
614
      String localId = DocumentUtil.getDocIdFromString(docid);
615
      int rev = DocumentUtil.getRevisionFromAccessionNumber(docid);
616
      String identifier = IdentifierManager.getInstance().getGUID(localId, rev);
617 6728 tao
      XMLAccessDAO xmlAccessDAO = new XMLAccessDAO();
618 6744 leinfelder
      xmlAccessDAO.setGuid(identifier);
619 6728 tao
      xmlAccessDAO.setPrincipalName(principalName);
620
      xmlAccessDAO.setPermission(Integer.valueOf(AccessControlList.intValue(permission)).longValue());
621
      xmlAccessDAO.setPermType(permType);
622
      xmlAccessDAO.setPermOrder(permOrder);
623
      return xmlAccessDAO;
624
    }
625
626
627
    /*
628
     * Remove every access rule for user public from the specified access rule list
629
     */
630
    private void removeAllPublicAccessRules(Vector<XMLAccessDAO> accessList) {
631
      if(accessList != null && !accessList.isEmpty()) {
632
        Vector<Integer> removingIndexList = new Vector<Integer>();
633
        for(int i=0; i<accessList.size(); i++) {
634
          XMLAccessDAO rule = accessList.elementAt(i);
635
          if(rule != null && rule.getPrincipalName() != null && rule.getPrincipalName().equalsIgnoreCase(AccessControlInterface.PUBLIC)) {
636
            //store the index which should be remove
637
            removingIndexList.add(new Integer(i));
638
          }
639
        }
640
        if(!removingIndexList.isEmpty()) {
641
          for(int i=removingIndexList.size()-1; i>=0; i--) {
642
            accessList.remove(removingIndexList.elementAt(i).intValue());
643
          }
644
       }
645
      }
646
    }
647
648 3517 barteau
    private String handleChangeAccess(String metaDocId, String permissionType) throws Exception {
649
        Stack                       dataDocIDs;
650
        String                      result = "", xpathExpr = null;
651
652
        setMetadataDoc(metaDocId);
653
        //*** Build list of sub-documents.
654
        if (clientViewBean.getContentStandard().equals(ClientView.FEDERAL_GEOGRAPHIC_DATA_COMMITTEE)) {
655
            xpathExpr = ClientFgdcHelper.SUB_DOCS_PATH;
656
        } else if (clientViewBean.getContentStandard().equals(ClientView.ECOLOGICAL_METADATA_LANGUAGE)) {
657
            xpathExpr = null; //TODO  - EML
658
        }
659
        if (xpathExpr != null) {
660
            dataDocIDs = getNodeTextStack(xpath, xpathExpr, getMetadataDoc().getDocumentElement());
661
            result = setPublicAccess(permissionType, metaDocId, dataDocIDs);
662
        }
663
        return(result);
664
    }
665
666 3364 barteau
    public String handleFileUpdate(MultipartParser multipartParser) throws Exception {
667 3457 barteau
        String                      result = "", fNm, action, lastDocId, newDocId, xPathQuery, qFrmt;
668 3364 barteau
        InputStream                 inputStream;
669
        HashMap                     paramsMap;
670 3486 barteau
        StringBuffer                fileName;
671 3364 barteau
        Iterator                    iterIt;
672
        boolean                     sendIt;
673 3372 barteau
        String                      metadataDocId, fileInfo[];
674 3364 barteau
675
        paramsMap = new HashMap();
676 3486 barteau
        fileName = new StringBuffer();
677 3364 barteau
        if ((inputStream = getNextInputStream(multipartParser, fileName, paramsMap)) != null) {
678
            action = (String) paramsMap.get("action");
679 3372 barteau
            //*** Get the Doc Id.
680 3364 barteau
            lastDocId = (String) paramsMap.get("docid");
681 3552 barteau
682 3372 barteau
            //*** Get the metadata Doc Id.
683
            metadataDocId = (String) paramsMap.get("metadataDocId");
684 3552 barteau
            clientViewBean.setMetaFileDocId(metadataDocId);
685
686 3457 barteau
            //*** Get the qformat.
687
            qFrmt = (String) paramsMap.get("qformat");
688 3552 barteau
            clientViewBean.setQformat(qFrmt);
689 3625 barteau
690 3364 barteau
            fNm = fileName.toString();
691 3372 barteau
692 3364 barteau
            try {
693 3372 barteau
                if (lastDocId.equals(metadataDocId)) { //*** This is the metadata file.
694 3364 barteau
                    //*** Keep it here for updating.
695
                    setMetadataDoc(inputStream);
696
                    if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
697 3372 barteau
                        clientViewBean.setContentStandard(ClientView.FEDERAL_GEOGRAPHIC_DATA_COMMITTEE);
698 3364 barteau
                        if (!ClientFgdcHelper.hasMetacatInfo(lastDocId, getMetadataDoc())) {
699 3457 barteau
700
                            //*** Save the Doc Id for re-query.
701
                            clientViewBean.setMetaFileDocId(lastDocId);
702
                            clientViewBean.setAction("read"); //*** Set for re-query.
703 3364 barteau
                            result = "Update not performed: the Metadata file has no prior Metacat info in it.";
704
                        } else {
705 3367 barteau
                            xPathQuery = ClientFgdcHelper.XPATH_QUERY_TEMPLATE.replaceFirst("%1s", lastDocId);
706 3372 barteau
                            newDocId = updateMetadataDoc(lastDocId, xPathQuery, fNm);
707 3457 barteau
708
                            //*** Save the Doc Id for re-query.
709
                            clientViewBean.setMetaFileDocId(newDocId);
710
                            clientViewBean.setAction("read"); //*** Set for re-query.
711
                            result = "Updated to new document (from " + lastDocId + " to " + newDocId + ")";
712 3364 barteau
                        }
713
                    } else {
714
                        //***TODO This is EML.
715 3372 barteau
                        clientViewBean.setContentStandard(ClientView.ECOLOGICAL_METADATA_LANGUAGE);
716 3457 barteau
717
                        //*** Save the Doc Id for re-query.
718
                        clientViewBean.setMetaFileDocId(lastDocId);
719
                        clientViewBean.setAction("read"); //*** Set for re-query.
720 3364 barteau
                        result = "Currently this functionality only supports FGDC metadata.";
721
                    }
722
                } else {
723
                    //*** This is a data file.
724 3372 barteau
                    //*** Query for the metadata, we need to update it with the new data file doc id.
725
                    setMetadataDoc(metadataDocId);
726 3457 barteau
727 3372 barteau
                    if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
728
                        clientViewBean.setContentStandard(ClientView.FEDERAL_GEOGRAPHIC_DATA_COMMITTEE);
729
                        fileInfo = parseFileInfo(fNm);
730
731
                        xPathQuery = ClientFgdcHelper.FGDC_DATA_FILE_QUERY_XPATH.replaceFirst("%1s", lastDocId);
732
                        newDocId = nextVersion(lastDocId, xPathQuery);
733
                        ClientFgdcHelper.updateFileNameAndType(getMetadataDoc().getDocumentElement(), newDocId, fileInfo);
734
                        //*** Upload the data file to metacat.
735 6684 tao
                        getMetacatClient().upload(newDocId, fNm, inputStream, DEFAULTFILESIZE);
736 3552 barteau
                        result = "Updated to new document (from " + lastDocId + " to " + newDocId + ")";
737 3372 barteau
738
                        //*** Upload the metadata file to metacat.
739 3375 barteau
                        xPathQuery = ClientFgdcHelper.XPATH_QUERY_TEMPLATE.replaceFirst("%1s", metadataDocId);
740 3372 barteau
                        newDocId = updateMetadataDoc(metadataDocId, xPathQuery, null);
741 3457 barteau
742
                        //*** Save the new meta Doc Id for re-query.
743
                        clientViewBean.setMetaFileDocId(newDocId);
744
                        clientViewBean.setAction("read"); //*** Set for re-query.
745
746 3372 barteau
                    } else {
747
                        //***TODO This is EML.
748
                        clientViewBean.setContentStandard(ClientView.ECOLOGICAL_METADATA_LANGUAGE);
749 3457 barteau
750
                        //*** Save the old meta Doc Id for re-query.
751
                        clientViewBean.setMetaFileDocId(metadataDocId);
752
                        clientViewBean.setAction("read"); //*** Set for re-query.
753 3372 barteau
                        result = "Currently this functionality only supports FGDC metadata.";
754
                    }
755 3364 barteau
                }
756
            } catch (java.io.IOException ex) {
757
                ex.printStackTrace();
758
            }
759
        } else {
760
            result = "Please enter the updated file path/name.";
761
        }
762 3457 barteau
        clientViewBean.setMessage(ClientView.UPDATE_MESSAGE, result);
763 3364 barteau
        return(result);
764
    }
765 3319 barteau
766 3372 barteau
    private String updateMetadataDoc(String lastDocId, String docIdPath, String origFileName) {
767
        String                      newDocId = null;
768
        Reader                      reader;
769
770
        //*** Update the metadata with the new Doc Id version.
771
        try {
772
            newDocId = nextVersion(lastDocId, docIdPath);
773
            if (origFileName != null) {
774
                if (clientViewBean.getContentStandard().equals(ClientView.FEDERAL_GEOGRAPHIC_DATA_COMMITTEE))
775
                    ClientFgdcHelper.updateMetadataFileName(getMetadataDoc().getDocumentElement(), newDocId, origFileName);
776
                else
777
                    ; //TODO EML, etc.
778
            }
779
            //*** Upload the metadata file to metacat.
780 3375 barteau
            reader = XMLUtilities.getDOMTreeAsReader(getMetadataDoc().getDocumentElement(), false);
781
            getMetacatClient().update(newDocId, reader, null);
782
            reader.close();
783 3372 barteau
        } catch (Exception ex) {
784
            ex.printStackTrace();
785
        }
786
        return(newDocId);
787
    }
788
789 3486 barteau
    private InputStream getNextInputStream(MultipartParser multipartParser, StringBuffer fileName, HashMap paramsMap)
790 3319 barteau
    throws IOException {
791
        InputStream                     result = null;
792
        Part                            part;
793
        String                          parmName = null, value = null, fnam;
794
795
        while ((part = multipartParser.readNextPart()) != null) {
796
            if (part.isParam()) {
797
                parmName = part.getName();
798
                value = ((ParamPart) part).getStringValue();
799
                paramsMap.put(parmName, value);
800
801
            } else if (part.isFile()) {
802
                fnam = ((FilePart) part).getFileName();
803
                if (fnam != null && !fnam.equals("")) {
804 3486 barteau
                    //*** File name is passed back via StringBuffer fileName param.
805 3319 barteau
                    fileName.append(fnam);
806
                    result = ((FilePart) part).getInputStream();
807
                    break;
808
                }
809
            }
810
        }
811
        return(result);
812
    }
813
814 3364 barteau
    private void getRemainingParameters(MultipartParser multipartParser, HashMap paramsMap)
815
    throws IOException {
816
        InputStream                     result = null;
817
        Part                            part;
818
        String                          parmName = null, value = null, fnam;
819
820
        while ((part = multipartParser.readNextPart()) != null) {
821
            if (part.isParam()) {
822
                parmName = part.getName();
823
                value = ((ParamPart) part).getStringValue();
824
                paramsMap.put(parmName, value);
825
            }
826
        }
827
    }
828
829 3319 barteau
    /**
830
     * Queries Metacat for document listings, and returns the results in a TreeMap,
831
     * where the key is the Doc Id, and the value is the Create Date.  If the document
832
     * contains the specified 'returnfield', an addtional entry will be created with
833
     * the value being a Vector of sub-DocId's.  The key of this entry will be the
834
     * original DocId with some addtional text added.
835
     * Reads bean properties 'pathExpr' (String[]), 'pathValue' (String)
836
     * and 'returnfield' (String).
837
     * @return TreeMap
838
     */
839
    public TreeMap getSelectQueryMap() {
840
        TreeMap                         result;
841
        Document                        doc;
842
        NodeList                        nodeLst, subNodeLst;
843
        Node                            node, subNode;
844
        String                          key, val, paramExpr, paramVal;
845
        String                          value, returnFld;
846
        String                          path;
847
        Vector                          optGroup;
848
        final String                    DOCID_EXPR = "./docid";
849
        final String                    DOCNAME_EXPR = "./createdate";
850 3367 barteau
        final String                    PARAM_EXPR = "./param[@name='%1s']";
851 3319 barteau
852
        path = clientViewBean.getPathExpr();
853
        returnFld = clientViewBean.getReturnfield();
854
        value = clientViewBean.getPathValue();
855
856
        result = new TreeMap();
857 3364 barteau
        //paramExpr = String.format(PARAM_EXPR, returnFld);
858 3367 barteau
        paramExpr = PARAM_EXPR.replaceFirst("%1s", returnFld);
859 3319 barteau
        //*** Query the database ***
860
        doc = query(path, value, returnFld);
861
        //*** Build the TreeMap to return ***
862
        try {
863
            nodeLst = (NodeList) xpath.evaluate("/resultset/document", doc, XPathConstants.NODESET);
864
            for (int i = 0; i < nodeLst.getLength(); i++) {
865
                node = nodeLst.item(i);
866
                key = xpath.evaluate(DOCID_EXPR, node);
867
                val = xpath.evaluate(DOCNAME_EXPR, node);
868
                result.put(key, key + " (" + val + ")");
869
870
                //*** returnfield values ***
871
                subNodeLst = (NodeList) xpath.evaluate(paramExpr, node, XPathConstants.NODESET);
872
                if (subNodeLst.getLength() > 0) {
873
                    optGroup = new Vector();
874
                    for (int k = 0; k < subNodeLst.getLength(); k++) {
875
                        subNode =  subNodeLst.item(k);
876
                        paramVal = xpath.evaluate("text()", subNode);
877
                        optGroup.add(paramVal);
878
                    }
879
                    result.put(key + " Data Files", optGroup);
880
                }
881
882
            }
883
        } catch (XPathExpressionException ex) {
884
            ex.printStackTrace();
885
        }
886
        return(result);
887
    }
888
889
    /**
890
     * Query metacat for documents that 'CONTAINS' the value at the specified XPath
891
     * expression.  Additionally, returns another non-standard field value.
892
     * Standard info contains: DocId, DocName, DocType, CreateDate, and UpdateDate.
893
     * @param pathExpr String contianing an XPath expression.
894
     * @param pathValue String containing a comparison value at the XPath expression.
895
     * @param returnFld String containing an XPath expression to a field which will be returned
896
     * in addition to the standard info.
897
     * @return DOM Document containing the results.
898
     */
899
    public Document query(String pathExpr, String pathValue, String returnFld) {
900
        Document                        result = null;
901
        InputStream                     response;
902
        BufferedReader                  buffy;
903
        Properties                      prop;
904
905
        try {
906
            prop = new Properties();
907
            prop.put("action", "query");
908
            prop.put("qformat", "xml");
909
            prop.put(pathExpr, pathValue);
910
            if (returnFld != null) {
911
                prop.put("returnfield", returnFld);
912
            }
913
914 5914 leinfelder
            response = metacatClient.sendParameters(prop);
915 3319 barteau
            if (response != null) {
916
                buffy = new BufferedReader(new InputStreamReader(response));
917
                result = XMLUtilities.getXMLReaderAsDOMDocument(buffy);
918
            }
919
        } catch (IOException ex) {
920
            ex.printStackTrace();
921
        } catch (Exception ex) {
922
            ex.printStackTrace();
923
        }
924
        return(result);
925
    }
926
927
    public void setMetadataDoc(Document doc) {
928
        metadataDoc = doc;
929
    }
930
931
    public void setMetadataDoc(String docId) throws Exception {
932
        Document                        doc = null;
933
        BufferedReader                  buffy;
934
        InputStream                     response;
935 5886 leinfelder
936
        response = metacatClient.read(docId);
937 3319 barteau
        if (response != null) {
938
            buffy = new BufferedReader(new InputStreamReader(response));
939
            doc = XMLUtilities.getXMLReaderAsDOMDocument(buffy);
940 3483 barteau
            response.close();
941 3319 barteau
        }
942
        setMetadataDoc(doc);
943
    }
944
945
    public void setMetadataDoc(InputStream ioStream) throws IOException {
946
        BufferedReader                          buffy;
947
948
        if (ioStream != null) {
949
            buffy = new BufferedReader(new InputStreamReader(ioStream));
950
            metadataDoc = XMLUtilities.getXMLReaderAsDOMDocument(buffy);
951
        }
952
    }
953
954
    public Document getMetadataDoc() {
955
        return(metadataDoc);
956
    }
957
958
    public String nextVersion(String lastDocId, String xPathQuery) throws XPathExpressionException {
959 3364 barteau
        String                      result = null, tokens[], scope, ready2Split, tmp;
960 3319 barteau
        int                         vers, docNum;
961
        final int                   LAST_TOKEN = 2;
962 3367 barteau
        final String                TEMPLATE = "%1s.%2d.%3d";
963 3319 barteau
        Node                        node;
964
965
        //*** Parse the last Doc Id, and increment the version number.
966 3539 barteau
        if(lastDocId != null && lastDocId.indexOf(".") > -1) {
967 3319 barteau
            ready2Split = lastDocId.replace('.','~'); //*** This is necessary for the split to work.
968
            tokens = ready2Split.split("~");
969
            if(tokens.length > LAST_TOKEN && !tokens[LAST_TOKEN].equals("")) {
970
                scope = tokens[LAST_TOKEN - 2];
971
                docNum = Integer.parseInt(tokens[LAST_TOKEN - 1]);
972
                try {
973
                    vers = Integer.parseInt(tokens[LAST_TOKEN]);
974 3364 barteau
                    //result = String.format(TEMPLATE, scope, docNum, 1 + vers);
975 3367 barteau
                    tmp = TEMPLATE.replaceFirst("%1s", scope);
976
                    tmp = tmp.replaceFirst("%2d", String.valueOf(docNum));
977
                    result = tmp.replaceFirst("%3d", String.valueOf(vers + 1));
978 3364 barteau
979 3319 barteau
                } catch (NumberFormatException ex) {
980
                    //*** In case the lastDocId has something other than a number.
981 3364 barteau
                    //result = String.format(TEMPLATE, scope, docNum, 1);
982 3367 barteau
                    tmp = TEMPLATE.replaceFirst("%1s", scope);
983
                    tmp = tmp.replaceFirst("%2d", String.valueOf(docNum));
984
                    result = tmp.replaceFirst("%3d", "1");
985 3319 barteau
                }
986
            } else {
987
                //*** In case the lastDocId ends with a '.'
988
                result = lastDocId + "1";
989
            }
990
        } else {
991
            //*** In case of missing doc Id.
992
            result = null;
993
        }
994
        //*** Update the Doc Id in the metadata file.
995
        if (getMetadataDoc() != null) {
996
            node = (Node) xpath.evaluate(xPathQuery, getMetadataDoc().getDocumentElement(), XPathConstants.NODE);
997 3539 barteau
            setTextContent(xpath, node, result);
998 3319 barteau
        }
999
        return(result);
1000
    }
1001
1002
    private String nextDocId(String lastDocId, String scope) {
1003 3364 barteau
        String                      result = null, tokens[], tmp;
1004 3319 barteau
        int                         vers;
1005 3367 barteau
        String                      template = scope.toLowerCase() + ".%1d.%2d";
1006 3319 barteau
1007 3539 barteau
        if(lastDocId != null && lastDocId.indexOf(".") > -1) {
1008 3319 barteau
            lastDocId = lastDocId.replace('.','~'); //*** This is necessary for the split to work.
1009
            tokens = lastDocId.split("~");
1010
            if(tokens.length > 1 && !tokens[1].equals("")) {
1011
                try {
1012
                    vers = Integer.parseInt(tokens[1]);
1013 3364 barteau
                    //result = String.format(template, 1 + vers, 1);
1014 3367 barteau
                    tmp = template.replaceFirst("%1d", String.valueOf(1 + vers));
1015
                    result = tmp.replaceFirst("%2d", "1");
1016 3319 barteau
                } catch (NumberFormatException ex) {
1017
                    //*** In case the lastDocId has something other than a number.
1018 3364 barteau
                    //result = String.format(template, 1, 1);
1019 3367 barteau
                    tmp = template.replaceFirst("%1d", "1");
1020
                    result = tmp.replaceFirst("%2d", "1");
1021 3319 barteau
                }
1022
            } else {
1023
                //*** In case the lastDocId ends with a '.'
1024 3364 barteau
                //result = String.format(template, 1, 1);
1025 3367 barteau
                tmp = template.replaceFirst("%1d", "1");
1026
                result = tmp.replaceFirst("%2d", "1");
1027 3319 barteau
            }
1028
        } else {
1029
            //*** In case there isn't any doc Id's with the user name.
1030 3364 barteau
            //result = String.format(template, 1, 1);
1031 3367 barteau
            tmp = template.replaceFirst("%1d", "1");
1032
            result = tmp.replaceFirst("%2d", "1");
1033 3319 barteau
        }
1034
        return(result);
1035
    }
1036
1037
    public MetacatClient getMetacatClient() {
1038
        return(metacatClient);
1039
    }
1040 3372 barteau
1041
    //*** BEGIN: Static utility methods ***
1042
1043
    public static String[] parseFileInfo(String fileName) {
1044
        String[]                        result = new String[2];
1045
        int                             idx;
1046
        String                          formatType;
1047
1048
        //*** Set the file format (just using file extension for now).
1049
        idx = fileName.lastIndexOf(".");
1050
        if (idx > 1)
1051
            formatType = fileName.substring(idx+1).toUpperCase();
1052
        else
1053
            formatType = "";
1054
1055
        result[ClientView.FORMAT_TYPE] = formatType;
1056
        result[ClientView.FILE_NAME] = fileName.toString();
1057
        return(result);
1058
    }
1059
1060
    public static void updateNodeText(Node root, XPath xPath, String expression, String text) {
1061
        Node                    targetNode;
1062
1063
        if (text != null && !text.equals("")) {
1064
            try {
1065
                targetNode = (Node) xPath.evaluate(expression, root, XPathConstants.NODE);
1066 3539 barteau
                setTextContent(xPath, targetNode, text);
1067
                //targetNode.setTextContent(text);
1068 3372 barteau
            } catch (XPathExpressionException ex) {
1069
                ex.printStackTrace();
1070
            }
1071
        }
1072
    }
1073
1074
1075
    public static Node getNode(XPath xPath, String expression, Node root) {
1076
        Node                        result = null;
1077
1078
        try {
1079
            result = (Node) xPath.evaluate(expression, root, XPathConstants.NODE);
1080
        } catch (XPathExpressionException ex) {
1081
            ex.printStackTrace();
1082
        }
1083
        return(result);
1084
1085
    }
1086 3457 barteau
1087 3483 barteau
    public static String getNodeText(XPath xPath, String expression, Node root) {
1088
        Node                        node;
1089
        String                      result = null;
1090
1091
        node = getNode(xPath, expression, root);
1092
        if (node != null && !node.equals(""))
1093 3539 barteau
            result = getTextContent(xPath, node);
1094
        //result = node.getTextContent(); Not in java 1.4
1095 3483 barteau
        return(result);
1096
    }
1097
1098
    public static String[] getNodeTextList(XPath xPath, String expression, Node root) {
1099
        NodeList                    nodes;
1100 3678 leinfelder
        String                      result[] = new String[0];
1101 3483 barteau
        int                         size;
1102
1103
        try {
1104
            nodes = (NodeList) xPath.evaluate(expression, root, XPathConstants.NODESET);
1105
            if (nodes != null && (size = nodes.getLength()) > 0) {
1106
                result = new String[size];
1107
                for(int i = 0; i < size; i++)
1108 3539 barteau
                    result[i] = getTextContent(xPath, nodes.item(i));
1109
                //result[i] = nodes.item(i).getTextContent(); Not in java 1.4
1110 3483 barteau
            }
1111
        } catch (XPathExpressionException ex) {
1112
            ex.printStackTrace();
1113
        }
1114
        return(result);
1115
    }
1116
1117 3517 barteau
    public static Stack getNodeTextStack(XPath xpathInstance, String xpathExpr, Node parentNode) {
1118
        String                      nodeLst[];
1119
        Stack                       result = new Stack();
1120
1121
        nodeLst = getNodeTextList(xpathInstance, xpathExpr, parentNode);
1122
        for(int i = 0; i < nodeLst.length; i++)
1123
            result.push(nodeLst[i]);
1124
        return(result);
1125
    }
1126
1127 3457 barteau
    public static String getStringFromInputStream(InputStream input) {
1128
        StringBuffer result = new StringBuffer();
1129
        BufferedReader in = new BufferedReader(new InputStreamReader(input));
1130
        String line;
1131
        try {
1132
            while ((line = in.readLine()) != null) {
1133
                result.append(line);
1134
            }
1135
        } catch (IOException e) {
1136
            System.out.println("ClientViewHelper.getStringFromInputStream: " + e);
1137
        }
1138
        return result.toString();
1139
    }
1140
1141 3372 barteau
    //*** END: Static utility methods ***
1142
1143 3457 barteau
    public String makeRedirectUrl() {
1144 3517 barteau
        String                      result, docId, message;
1145 3457 barteau
1146
        docId = clientViewBean.getMetaFileDocId();
1147 6696 tao
        //System.out.println("get the the session id "+clientViewBean.getSessionid()+ " from the client view bean object "+clientViewBean.toString());
1148 3483 barteau
        if (clientViewBean.getAction().equals(DOWNLOAD_ACTION)) {
1149
            result = null;
1150
        } else if (docId != null && !docId.equals("")) {
1151 3517 barteau
            message = clientViewBean.getMessage(ClientView.UPDATE_MESSAGE);
1152 3483 barteau
            result = "metacat?action=read&qformat=" +clientViewBean.getQformat()
1153 3517 barteau
            + "&docid=" + docId + "&sessionid=" + clientViewBean.getSessionid() + "&message=" + message;
1154 3457 barteau
        } else {
1155 3603 barteau
            result = "style/skins/" + clientViewBean.getQformat() + "/confirm.jsp";
1156 3457 barteau
        }
1157
        //*** Reset bean action property.
1158
        clientViewBean.setAction("");
1159
        return(result);
1160
    }
1161
1162 6059 leinfelder
    private HashMap<String, Object> download(ClientView bean) {
1163 3483 barteau
        Properties                      args;
1164
        InputStream                     inStream;
1165
        String                          docId, metaId, fNm = null, pth, txtLst[];
1166
        String                          msg = "File '~' (~) downloaded";
1167
        Node                            branchRoot, metaRoot;
1168
        ByteArrayOutputStream           outStream;
1169
        int                             intMe;
1170 6059 leinfelder
        HashMap<String, Object>         responseMap = new HashMap<String, Object>();
1171 3483 barteau
1172
        docId = bean.getDocId();
1173
        metaId = bean.getMetaFileDocId();
1174
        if (docId != null && metaId != null && !docId.equals("") && !metaId.equals("")) {
1175
            //*** Properties args: key=param_value, value=param_name.
1176
            args = new Properties();
1177
            args.put("read", "action");
1178
            try {
1179
                //*** First, retrieve the metadata and get the original filename.
1180
                //*** Also, if this is the metadata, get a list of docId's for the package.
1181
                setMetadataDoc(metaId);
1182
                metaRoot = getMetadataDoc().getDocumentElement();
1183
                if (ClientFgdcHelper.isFGDC(getMetadataDoc())) {
1184
                    //*** FGDC
1185
                    if (docId.equals(metaId)) { //*** This is the metadata file.
1186
                        pth = ClientFgdcHelper.FGDC_DOCID_ROOT_XPATH.replaceFirst("%1s", docId);
1187
                        branchRoot = getNode(xpath, pth, getMetadataDoc());
1188
                        fNm = getNodeText(xpath, ClientFgdcHelper.FGDC_FILE_NAME_XPATH, branchRoot);
1189 3772 leinfelder
                        //include the filename for the docid
1190
                        args.put(fNm, docId);
1191 3483 barteau
                        fNm = toZipFileName(fNm);
1192 3530 barteau
                        responseMap.put("contentType", "application/zip");
1193 3483 barteau
                        //*** Get the list of docId's for the entire package.
1194
                        args.put(metaId, "docid");
1195
                        txtLst = getNodeTextList(xpath, ClientFgdcHelper.FGDC_DATA_FILE_NODES_XPATH, branchRoot);
1196 3772 leinfelder
                        for (int i = 0; i < txtLst.length; i++) {
1197
                        	String additionalDocId = txtLst[i];
1198
                        	if (additionalDocId != null && additionalDocId.length() > 1) {
1199
                        		//look up the filename from the metadata
1200
                        		String tempPath = ClientFgdcHelper.PATH4ANCESTOR.replaceFirst("%1s", additionalDocId);
1201
                        		tempPath = tempPath.replaceFirst("%2s", "digform");
1202
                                Node tempBranchRoot = getNode(xpath, tempPath, getMetadataDoc());
1203
                                String tempFileName = getNodeText(xpath, ClientFgdcHelper.FGDC_DATA_FILE_NAME_XPATH, tempBranchRoot);
1204
                                //include the docid
1205
                        		args.put(additionalDocId, "docid");
1206
                        		//include the filename for the docid
1207
                        		args.put(tempFileName, additionalDocId);
1208
                        	}
1209
                        }
1210 3483 barteau
                        args.put("zip", "qformat");
1211
                    } else { //*** This is a data file.
1212
                        pth = ClientFgdcHelper.PATH4ANCESTOR.replaceFirst("%1s", docId);
1213
                        pth = pth.replaceFirst("%2s", "digform");
1214
                        branchRoot = getNode(xpath, pth, getMetadataDoc());
1215
                        fNm = getNodeText(xpath, ClientFgdcHelper.FGDC_DATA_FILE_NAME_XPATH, branchRoot);
1216 3530 barteau
                        responseMap.put("contentType", "application/octet-stream");
1217 3483 barteau
                        args.put(docId, "docid");
1218
                        args.put("xml", "qformat");
1219
                    }
1220
                } else {
1221
                    //*** TODO: EML -  this is just some basic code to start with.
1222
                    if (docId.equals(metaId)) {
1223
                        fNm = "emlMetadata.xml";
1224
                        txtLst = new String[] {docId};
1225
                        args.put(txtLst[0], "docid");
1226
                        args.put("zip", "qformat");
1227 3530 barteau
                        responseMap.put("contentType", "application/zip");
1228 3483 barteau
                    } else {
1229
                        fNm = "emlData.dat";
1230
                        args.put("xml", "qformat");
1231
                        args.put(docId, "docid");
1232 3530 barteau
                        responseMap.put("contentType", "application/octet-stream");
1233 3483 barteau
                    }
1234
                }
1235
1236
                //*** Set the filename in the response.
1237 3530 barteau
                responseMap.put("Content-Disposition", "attachment; filename=" + fNm);
1238 3483 barteau
1239
                //*** Next, read the file from metacat.
1240 7395 leinfelder
                inStream = metacatClient.sendParametersInverted(args);
1241 3483 barteau
1242
                //*** Then, convert the input stream into an output stream.
1243
                outStream = new ByteArrayOutputStream();
1244
                while ((intMe = inStream.read()) != -1) {
1245
                    outStream.write(intMe);
1246
                }
1247
1248
                //*** Now, write the output stream to the response.
1249 6059 leinfelder
                responseMap.put("outputStream", outStream);
1250 3483 barteau
1251
                //*** Finally, set the message for the user interface to display.
1252
                msg = msg.replaceFirst("~", fNm);
1253
                msg = msg.replaceFirst("~", docId);
1254
                bean.setMessage(ClientView.SELECT_MESSAGE, msg);
1255
            } catch (Exception ex) {
1256
                ex.printStackTrace();
1257
                bean.setMessage(ClientView.SELECT_MESSAGE, ex.getMessage());
1258
            }
1259
        }
1260 3539 barteau
        responseMap.put("message", bean.getMessage(ClientView.SELECT_MESSAGE));
1261 3530 barteau
        return(responseMap);
1262 3483 barteau
    }
1263
1264 3530 barteau
    private void handleDownloadResponse(HashMap responseMap, HttpServletResponse response) throws IOException {
1265
        ByteArrayOutputStream                       outStream;
1266
        String                                      contentDisposition, contentType;
1267
1268
        contentType = (String) responseMap.get("contentType");
1269
        contentDisposition = (String) responseMap.get("Content-Disposition");
1270
        outStream = (ByteArrayOutputStream) responseMap.get("outputStream");
1271
1272
        response.setContentType(contentType);
1273
        response.setHeader("Content-Disposition", contentDisposition);
1274
        response.setContentLength(outStream.size());
1275
        outStream.writeTo(response.getOutputStream());
1276
        response.flushBuffer();
1277
    }
1278
1279 3483 barteau
    public static String toZipFileName(String fileName) {
1280
        String                      result = "metacat";
1281
        int                         idx;
1282
1283
        if (fileName != null && !fileName.equals("") && !fileName.equals(".")) {
1284
            idx = fileName.indexOf('.');
1285
            if (idx > -1)
1286
                result = fileName.substring(0, idx);
1287
            else
1288
                result = fileName;
1289
        }
1290
        result += ".zip";
1291
        return(result);
1292
    }
1293 3530 barteau
1294 3539 barteau
    public static void setTextContent(XPath xPath, Node elementNode, String content) throws DOMException {
1295
        Text                        textNode, newTxtNode;
1296
        Document                    document;
1297
1298
        textNode = (Text) getNode(xPath, "text()", elementNode);
1299
        if (textNode != null) {
1300
            if (isElementContentWhitespace(textNode)) {
1301
                //*** If there is an existing text node, and it's whitespace,
1302
                //*** create a new text node and insert it before whitespace.
1303
                document = elementNode.getOwnerDocument();
1304
                newTxtNode = document.createTextNode(content);
1305
                elementNode.insertBefore(newTxtNode, textNode);
1306
            } else {
1307
                //*** If there is an existing text node, and it has content,
1308
                //*** overwrite the existing text.
1309
                textNode.setNodeValue(content);
1310
            }
1311
        } else {
1312
            //*** If there isn't an existing text node,
1313
            //*** create a new text node and append it to the elementNode.
1314
            document = elementNode.getOwnerDocument();
1315
            newTxtNode = document.createTextNode(content);
1316
            elementNode.appendChild(newTxtNode);
1317
        }
1318
    }
1319
1320
    public static String getTextContent(XPath xPath, Node elementNode) throws DOMException {
1321
        String                      result = "";
1322
        Text                        textNode;
1323
1324 3625 barteau
        if (elementNode.getNodeType() != Node.TEXT_NODE)
1325
            textNode = (Text) getNode(xPath, "text()", elementNode);
1326
        else
1327
            textNode = (Text) elementNode;
1328 3539 barteau
        if (textNode != null)
1329
            result = textNode.getNodeValue();
1330
        return(result);
1331
    }
1332
1333
    public static boolean isElementContentWhitespace(Text textNode) {
1334
        boolean                     result = false;
1335
        String                      val;
1336
1337
        if ((val = textNode.getNodeValue()) != null) {
1338
            if (val != null) {
1339
                val = val.trim();
1340
                result = (val.length() == 0);
1341
            }
1342
        }
1343
        return(result);
1344
    }
1345
1346 3319 barteau
}