Project

General

Profile

1 1780 jones
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2000 Regents of the University of California and the
4
 *              National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author$'
7
 *     '$Date$'
8
 * '$Revision$'
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program; if not, write to the Free Software
22
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 */
24
25
package edu.ucsb.nceas.metacat.client;
26
27 3285 barteau
import com.oreilly.servlet.multipart.FilePart;
28
import com.oreilly.servlet.multipart.MultipartParser;
29
import com.oreilly.servlet.multipart.ParamPart;
30
import com.oreilly.servlet.multipart.Part;
31
import edu.ucsb.nceas.metacat.MetaCatUtil;
32
import java.io.BufferedInputStream;
33 1786 tao
import java.io.BufferedReader;
34 1780 jones
import java.io.InputStream;
35 1783 jones
import java.io.InputStreamReader;
36 1784 jones
import java.io.PushbackReader;
37 2981 jones
import java.io.StringReader;
38 1784 jones
import java.io.IOException;
39 1783 jones
import java.io.StringWriter;
40 1780 jones
import java.io.Reader;
41
import java.net.URL;
42 3285 barteau
import java.util.HashMap;
43
import java.util.Iterator;
44 1780 jones
import java.util.Properties;
45 3141 berkley
import java.util.Vector;
46 3285 barteau
import javax.xml.xpath.XPath;
47
import javax.xml.xpath.XPathFactory;
48
import org.w3c.dom.Document;
49
import org.w3c.dom.DocumentType;
50
import org.w3c.dom.Element;
51 1780 jones
52 2981 jones
import org.w3c.dom.Node;
53 3141 berkley
import org.w3c.dom.NodeList;
54 2981 jones
55 1780 jones
import edu.ucsb.nceas.utilities.HttpMessage;
56 1788 jones
import edu.ucsb.nceas.utilities.IOUtil;
57 2981 jones
import edu.ucsb.nceas.utilities.XMLUtilities;
58 2240 sgarg
import java.io.File;
59 3285 barteau
import javax.xml.xpath.XPathConstants;
60
import javax.xml.xpath.XPathExpressionException;
61 1780 jones
62 1788 jones
63 1780 jones
/**
64 2240 sgarg
 *  This interface provides methods for initializing and logging in to a
65
 *  Metacat server, and then querying, reading, transforming, inserting,
66 1780 jones
 *  updating and deleting documents from that server.
67
 */
68 3285 barteau
public class MetacatClient implements Metacat {
69 1780 jones
    /** The URL string for the metacat server */
70
    private String metacatUrl;
71 3285 barteau
72 1822 jones
    /** The session identifier for the session */
73
    private String sessionId;
74 3285 barteau
75
    public static final String              FGDC_SYSTEM_ID = "http://www.fgdc.gov/metadata/fgdc-std-001-1998.dtd";
76
    private static XPath                    xpath = XPathFactory.newInstance().newXPath();
77
    private Document                        loginResponse = null, metadataDoc = null;
78
    private String                          user = null;
79
80 1780 jones
    /**
81 3285 barteau
     * The Login cookie name.
82
     */
83
    public final static String                    LOGIN_COOOKIE = "cookie";
84
85
    /**
86 1780 jones
     * Constructor to create a new instance. Protected because instances
87
     * should only be created by the factory MetacatFactory.
88
     */
89 3285 barteau
    protected MetacatClient() {
90 1822 jones
        this.metacatUrl = null;
91
        this.sessionId = null;
92 1780 jones
    }
93 3285 barteau
94 1780 jones
    /**
95
     *  Method used to log in to a metacat server. Implementations will need
96
     *  to cache a cookie value to make the session persistent.  Each time a
97
     *  call is made to one of the other methods (e.g., read), the cookie will
98
     *  need to be passed back to the metacat server along with the request.
99
     *
100
     *  @param username   the username of the user, like an LDAP DN
101
     *  @param password   the password for that user for authentication
102 1822 jones
     *  @return the response string from metacat in XML format
103 1780 jones
     *  @throws MetacatAuthException when the username/password could
104
     *                    not be authenticated
105
     */
106 2240 sgarg
    public String login(String username, String password)
107 3285 barteau
    throws MetacatAuthException, MetacatInaccessibleException {
108 1783 jones
        Properties prop = new Properties();
109
        prop.put("action", "login");
110
        prop.put("qformat", "xml");
111
        prop.put("username", username);
112
        prop.put("password", password);
113 3285 barteau
114 1783 jones
        String response = null;
115
        try {
116 2264 sgarg
            response = sendDataForString(prop, null, null, 0);
117 1783 jones
        } catch (Exception e) {
118
            throw new MetacatInaccessibleException(e.getMessage());
119
        }
120 3285 barteau
121 1783 jones
        if (response.indexOf("<login>") == -1) {
122 1828 jones
            setSessionId("");
123 1783 jones
            throw new MetacatAuthException(response);
124 1822 jones
        } else {
125 1825 jones
            int start = response.indexOf("<sessionId>") + 11;
126 1822 jones
            int end = response.indexOf("</sessionId>");
127
            if ((start != -1) && (end != -1)) {
128 1828 jones
                setSessionId(response.substring(start,end));
129 1822 jones
            }
130 1783 jones
        }
131 1822 jones
        return response;
132 1780 jones
    }
133 2683 sgarg
134
    /**
135
     *  Method used to log in to a metacat server. Implementations will need
136
     *  to cache a cookie value to make the session persistent.  Each time a
137
     *  call is made to one of the other methods (e.g., read), the cookie will
138
     *  need to be passed back to the metacat server along with the request.
139
     *
140
     *  @param username   the username of the user, like an LDAP DN
141
     *  @param password   the password for that user for authentication
142
     *  @return the response string from metacat in XML format
143
     *  @throws MetacatAuthException when the username/password could
144
     *                    not be authenticated
145
     */
146 3285 barteau
    public String getloggedinuserinfo() throws MetacatInaccessibleException {
147 2683 sgarg
        Properties prop = new Properties();
148
        prop.put("action", "getloggedinuserinfo");
149
        prop.put("qformat", "xml");
150 3285 barteau
151 2683 sgarg
        String response = null;
152
        try {
153
            response = sendDataForString(prop, null, null, 0);
154
        } catch (Exception e) {
155
            throw new MetacatInaccessibleException(e.getMessage());
156
        }
157 3285 barteau
158 2683 sgarg
        return response;
159
    }
160 3285 barteau
161 1780 jones
    /**
162 1822 jones
     *  Method used to log out a metacat server. The Metacat server will end
163
     *  the session when this call is invoked.
164 1798 tao
     *
165 1822 jones
     *  @return the response string from metacat in XML format
166 1798 tao
     *  @throws MetacatInaccessibleException when the metacat server can not be
167
     *                                    reached or does not respond
168
     */
169 3285 barteau
    public String logout() throws MetacatInaccessibleException, MetacatException {
170 1798 tao
        Properties prop = new Properties();
171
        prop.put("action", "logout");
172 2240 sgarg
        prop.put("qformat", "xml");
173 3285 barteau
174 1798 tao
        String response = null;
175
        try {
176 2264 sgarg
            response = sendDataForString(prop, null, null, 0);
177 1798 tao
        } catch (Exception e) {
178
            throw new MetacatInaccessibleException(e.getMessage());
179
        }
180 3285 barteau
181 1798 tao
        if (response.indexOf("<logout>") == -1) {
182
            throw new MetacatException(response);
183
        }
184 1828 jones
        setSessionId("");
185 1822 jones
        return response;
186 1798 tao
    }
187 3285 barteau
188 1798 tao
    /**
189 1780 jones
     * Read an XML document from the metacat server session, accessed by docid,
190
     * and returned as a Reader.
191
     *
192
     * @param docid the identifier of the document to be read
193
     * @return a Reader for accessing the document
194 2240 sgarg
     * @throws InsufficientKarmaException when the user has insufficent rights
195 1780 jones
     *                                    for the operation
196 1784 jones
     * @throws MetacatInaccessibleException when the metacat server can not be
197
     *                                    reached or does not respond
198
     * @throws MetacatException when the metacat server generates another error
199 1780 jones
     */
200 1784 jones
    public Reader read(String docid) throws InsufficientKarmaException,
201 3285 barteau
            MetacatInaccessibleException, MetacatException, DocumentNotFoundException {
202 1784 jones
        PushbackReader pbr = null;
203 3285 barteau
204 1784 jones
        Properties prop = new Properties();
205
        prop.put("action", "read");
206
        prop.put("qformat", "xml");
207
        prop.put("docid", docid);
208
        InputStream response = null;
209
        try {
210 2264 sgarg
            response = sendData(prop, null, null, 0);
211 1784 jones
        } catch (Exception e) {
212
            throw new MetacatInaccessibleException(e.getMessage());
213
        }
214
        pbr = new PushbackReader(new InputStreamReader(response), 512);
215
        try {
216
            char[] characters = new char[512];
217
            int len = pbr.read(characters, 0, 512);
218
            StringWriter sw = new StringWriter();
219
            sw.write(characters, 0, len);
220
            String message = sw.toString();
221
            sw.close();
222
            pbr.unread(characters, 0, len);
223
            if (message.indexOf("<error>") != -1) {
224
                if (message.indexOf("does not have permission") != -1) {
225
                    throw new InsufficientKarmaException(message);
226 2989 berkley
                } else if(message.indexOf("does not exist") != -1) {
227
                    throw new DocumentNotFoundException(message);
228 1784 jones
                } else {
229
                    throw new MetacatException(message);
230
                }
231
            }
232
        } catch (IOException ioe) {
233
            throw new MetacatException(
234 2240 sgarg
                    "MetacatClient: Error converting Reader to String."
235 1784 jones
                    + ioe.getMessage());
236
        }
237
        return pbr;
238 1780 jones
    }
239 3285 barteau
240
241 1780 jones
    /**
242 3285 barteau
     * Read inline data from the metacat server session, accessed by
243
     * inlinedataid and returned as a Reader.
244
     *
245
     * @param inlinedataid the identifier of the data to be read
246
     * @return a Reader for accessing the document
247
     * @throws InsufficientKarmaException when the user has insufficent rights
248
     *                                    for the operation
249
     * @throws MetacatInaccessibleException when the metacat server can not be
250
     *                                    reached or does not respond
251
     * @throws MetacatException when the metacat server generates another error
252
     */
253
    public Reader readInlineData(String inlinedataid)
254
    throws InsufficientKarmaException,
255
            MetacatInaccessibleException, MetacatException {
256
        PushbackReader pbr = null;
257
258
        Properties prop = new Properties();
259
        prop.put("action", "readinlinedata");
260
        prop.put("inlinedataid", inlinedataid);
261
262
        InputStream response = null;
263
        try {
264
            response = sendData(prop, null, null, 0);
265
        } catch (Exception e) {
266
            throw new MetacatInaccessibleException(e.getMessage());
267
        }
268
269
        pbr = new PushbackReader(new InputStreamReader(response), 512);
270
        try {
271
            char[] characters = new char[512];
272
            int len = pbr.read(characters, 0, 512);
273
            StringWriter sw = new StringWriter();
274
            sw.write(characters, 0, len);
275
            String message = sw.toString();
276
            sw.close();
277
            pbr.unread(characters, 0, len);
278
279
            if (message.indexOf("<error>") != -1) {
280
                if (message.indexOf("does not have permission") != -1) {
281
                    throw new InsufficientKarmaException(message);
282
                } else {
283
                    throw new MetacatException(message);
284
                }
285
            }
286
        } catch (IOException ioe) {
287
            throw new MetacatException(
288
                    "MetacatClient: Error converting Reader to String."
289
                    + ioe.getMessage());
290
        }
291
292
        return pbr;
293
    }
294
295 2261 sgarg
    /**
296 2240 sgarg
     * Query the metacat document store with the given metacat-compatible
297 1780 jones
     * query document, and return the result set as a Reader.
298
     *
299
     * @param xmlQuery a Reader for accessing the XML version of the query
300
     * @return a Reader for accessing the result set
301
     */
302 1786 tao
    public Reader query(Reader xmlQuery) throws MetacatInaccessibleException,
303 3285 barteau
            IOException {
304 1786 tao
        Reader reader = null;
305
        String query = null;
306 1788 jones
        try {
307 3285 barteau
            query = IOUtil.getAsString(xmlQuery, true);
308 1788 jones
        } catch (IOException ioE) {
309 3285 barteau
            throw ioE;
310 1786 tao
        }
311 3285 barteau
312 1786 tao
        //set up properties
313
        Properties prop = new Properties();
314
        prop.put("action", "squery");
315
        prop.put("qformat", "xml");
316
        prop.put("query", query);
317 3285 barteau
318 1786 tao
        InputStream response = null;
319
        try {
320 2264 sgarg
            response = sendData(prop, null, null, 0);
321 1786 tao
        } catch (Exception e) {
322
            throw new MetacatInaccessibleException(e.getMessage());
323
        }
324
        reader = new InputStreamReader(response);
325
        return reader;
326 1780 jones
    }
327 3285 barteau
328 1780 jones
    /**
329
     * Insert an XML document into the repository.
330
     *
331
     * @param docid the docid to insert the document
332
     * @param xmlDocument a Reader for accessing the XML document to be inserted
333 2240 sgarg
     * @param schema a Reader for accessing the DTD or XML Schema for
334 1780 jones
     *               the document
335 1789 jones
     * @return the metacat response message
336 2240 sgarg
     * @throws InsufficientKarmaException when the user has insufficent rights
337 1780 jones
     *                                    for the operation
338 1789 jones
     * @throws MetacatInaccessibleException when the metacat server can not be
339
     *                                    reached or does not respond
340
     * @throws MetacatException when the metacat server generates another error
341
     * @throws IOException when there is an error reading the xml document
342 1780 jones
     */
343 1789 jones
    public String insert(String docid, Reader xmlDocument, Reader schema)
344 3285 barteau
    throws InsufficientKarmaException, MetacatException, IOException,
345
            MetacatInaccessibleException {
346 1789 jones
        Reader reader = null;
347
        String doctext = null;
348
        String schematext = null;
349
        try {
350 3285 barteau
            doctext = IOUtil.getAsString(xmlDocument, true);
351
            if (schema != null) {
352
                schematext = IOUtil.getAsString(schema, true);
353
            }
354 1789 jones
        } catch (IOException ioE) {
355 3285 barteau
            throw ioE;
356 1789 jones
        }
357 3285 barteau
358 1789 jones
        //set up properties
359
        Properties prop = new Properties();
360
        prop.put("action", "insert");
361
        prop.put("docid", docid);
362
        prop.put("doctext", doctext);
363
        if (schematext != null) {
364
            prop.put("dtdtext", schematext);
365
        }
366 3285 barteau
367 1789 jones
        String response = null;
368
        try {
369 2264 sgarg
            response = sendDataForString(prop, null, null, 0);
370 1789 jones
        } catch (Exception e) {
371
            throw new MetacatInaccessibleException(e.getMessage());
372
        }
373 3285 barteau
374 1789 jones
        // Check for an error condition
375
        if (response.indexOf("<error>") != -1) {
376
            if (response.indexOf("does not have permission") != -1) {
377
                throw new InsufficientKarmaException(response);
378
            } else {
379
                throw new MetacatException(response);
380
            }
381
        }
382 3285 barteau
383 1789 jones
        return response;
384 1780 jones
    }
385 3285 barteau
386 1780 jones
    /**
387
     * Update an XML document in the repository.
388
     *
389
     * @param docid the docid to update
390
     * @param xmlDocument a Reader for accessing the XML text to be updated
391 2240 sgarg
     * @param schema a Reader for accessing the DTD or XML Schema for
392 1780 jones
     *               the document
393 1795 jones
     * @return the metacat response message
394 2240 sgarg
     * @throws InsufficientKarmaException when the user has insufficent rights
395 1780 jones
     *                                    for the operation
396 1795 jones
     * @throws MetacatInaccessibleException when the metacat server can not be
397
     *                                    reached or does not respond
398
     * @throws MetacatException when the metacat server generates another error
399
     * @throws IOException when there is an error reading the xml document
400 1780 jones
     */
401 1795 jones
    public String update(String docid, Reader xmlDocument, Reader schema)
402 3285 barteau
    throws InsufficientKarmaException, MetacatException, IOException,
403
            MetacatInaccessibleException {
404 1795 jones
        Reader reader = null;
405
        String doctext = null;
406
        String schematext = null;
407
        try {
408 3285 barteau
            doctext = IOUtil.getAsString(xmlDocument, true);
409
            if (schema != null) {
410
                schematext = IOUtil.getAsString(schema, true);
411
            }
412 1795 jones
        } catch (IOException ioE) {
413 3285 barteau
            throw ioE;
414 1795 jones
        }
415 3285 barteau
416 1795 jones
        //set up properties
417
        Properties prop = new Properties();
418
        prop.put("action", "update");
419
        prop.put("docid", docid);
420
        prop.put("doctext", doctext);
421
        if (schematext != null) {
422
            prop.put("dtdtext", schematext);
423
        }
424 3285 barteau
425 1795 jones
        String response = null;
426
        try {
427 2264 sgarg
            response = sendDataForString(prop, null, null, 0);
428 1795 jones
        } catch (Exception e) {
429
            throw new MetacatInaccessibleException(e.getMessage());
430
        }
431 3285 barteau
432 1795 jones
        // Check for an error condition
433
        if (response.indexOf("<error>") != -1) {
434
            if (response.indexOf("does not have permission") != -1) {
435
                throw new InsufficientKarmaException(response);
436
            } else {
437
                throw new MetacatException(response);
438
            }
439
        }
440 3285 barteau
441 1795 jones
        return response;
442 1780 jones
    }
443 3285 barteau
444 1780 jones
    /**
445 3285 barteau
     * Upload a data document into the repository.
446
     *
447
     * @param docid the docid to insert the document
448
     * @param document a Reader for accessing the document to be uploaded
449
     * @return the metacat response message
450
     * @throws InsufficientKarmaException when the user has insufficent rights
451
     *                                    for the operation
452
     * @throws MetacatInaccessibleException when the metacat server can not be
453
     *                                    reached or does not respond
454
     * @throws MetacatException when the metacat server generates another error
455
     * @throws IOException when there is an error reading the xml document
456
     */
457
    public String upload(String docid, File file)
458
    throws InsufficientKarmaException, MetacatException, IOException,
459
            MetacatInaccessibleException {
460
461
        URL url = new URL(metacatUrl.trim());
462
        HttpMessage msg = new HttpMessage(url);
463
        //set up properties
464
        Properties arg = new Properties();
465
        arg.put("action", "upload");
466
        arg.put("docid", docid);
467
468
        Properties filenames = new Properties();
469
        String filename = file.getAbsolutePath();
470
        filenames.put("datafile", filename);
471
472
        String response = null;
473
        try {
474 2264 sgarg
            response = sendDataForString(arg, filenames, null, 0);
475 3285 barteau
        } catch (Exception e) {
476 2240 sgarg
            throw new MetacatInaccessibleException(e.getMessage());
477 3285 barteau
        }
478
479
        // Check for an error condition
480
        if (response.indexOf("<error>") != -1) {
481 2240 sgarg
            if (response.indexOf("does not have permission") != -1) {
482 3285 barteau
                throw new InsufficientKarmaException(response);
483 2240 sgarg
            } else {
484 3285 barteau
                throw new MetacatException(response);
485 2240 sgarg
            }
486 3285 barteau
        }
487
488
        return response;
489
    }
490
491
    /**
492
     * Upload a data document into the repository.
493
     *
494
     * @param docid the docid to insert the document
495
     * @param document a Reader for accessing the document to be uploaded
496
     * @return the metacat response message
497
     * @throws InsufficientKarmaException when the user has insufficent rights
498
     *                                    for the operation
499
     * @throws MetacatInaccessibleException when the metacat server can not be
500
     *                                    reached or does not respond
501
     * @throws MetacatException when the metacat server generates another error
502
     * @throws IOException when there is an error reading the xml document
503
     */
504
505
506
    public String upload(String docid, String filename, InputStream fileData,
507
            int size)
508
            throws InsufficientKarmaException, MetacatException, IOException,
509
            MetacatInaccessibleException {
510
511
        URL url = new URL(metacatUrl.trim());
512
        HttpMessage msg = new HttpMessage(url);
513
        //set up properties
514
        Properties arg = new Properties();
515
        arg.put("action", "upload");
516
        arg.put("docid", docid);
517
518
        Properties filenames = new Properties();
519
        filenames.put("datafile", filename);
520
521
        String response = null;
522
        try {
523 2264 sgarg
            response = sendDataForString(arg, filenames, fileData, size);
524 3285 barteau
        } catch (Exception e) {
525 2264 sgarg
            throw new MetacatInaccessibleException(e.getMessage());
526 3285 barteau
        }
527
528
        // Check for an error condition
529
        if (response.indexOf("<error>") != -1) {
530 2264 sgarg
            if (response.indexOf("does not have permission") != -1) {
531 3285 barteau
                throw new InsufficientKarmaException(response);
532 2264 sgarg
            } else {
533 3285 barteau
                throw new MetacatException(response);
534 2264 sgarg
            }
535 3285 barteau
        }
536
537
        return response;
538
    }
539
540 2240 sgarg
    /**
541 1780 jones
     * Delete an XML document in the repository.
542
     *
543
     * @param docid the docid to delete
544 1795 jones
     * @return the metacat response message
545 2240 sgarg
     * @throws InsufficientKarmaException when the user has insufficent rights
546 1780 jones
     *                                    for the operation
547 1795 jones
     * @throws MetacatInaccessibleException when the metacat server can not be
548
     *                                    reached or does not respond
549
     * @throws MetacatException when the metacat server generates another error
550 1780 jones
     */
551 1795 jones
    public String delete(String docid)
552 3285 barteau
    throws InsufficientKarmaException, MetacatException,
553
            MetacatInaccessibleException {
554 1795 jones
        //set up properties
555
        Properties prop = new Properties();
556
        prop.put("action", "delete");
557
        prop.put("docid", docid);
558 3285 barteau
559 1795 jones
        String response = null;
560
        try {
561 2264 sgarg
            response = sendDataForString(prop, null, null, 0);
562 1795 jones
        } catch (Exception e) {
563
            throw new MetacatInaccessibleException(e.getMessage());
564
        }
565 3285 barteau
566 1795 jones
        // Check for an error condition
567
        if (response.indexOf("<error>") != -1) {
568
            if (response.indexOf("does not have permission") != -1) {
569
                throw new InsufficientKarmaException(response);
570
            } else {
571
                throw new MetacatException(response);
572
            }
573
        }
574 2326 harris
        return response;
575
    }
576 3285 barteau
577
578 2326 harris
    /**
579
     * set the access on an XML document in the repository.
580
     *
581 2327 harris
     * @param _docid the docid of the document for which the access should be applied.
582 2326 harris
     *
583
     * @param _principal the document's principal
584
     *
585
     * @param _permission the access permission to be applied to the docid
586
     *  {e.g. read,write,all}
587
     *
588
     * @param _permType the permission type to be applied to the document
589
     *  {e.g. allow or deny}
590
     *
591
     * @param _permOrder the order that the document's permissions should be
592
     *  processed {e.g. denyFirst or allowFirst}
593
     *
594
     *
595
     * @return the metacat response message
596
     *
597
     * @throws InsufficientKarmaException when the user has insufficent rights
598
     *                                    for the operation
599
     * @throws MetacatInaccessibleException when the metacat server can not be
600
     *                                    reached or does not respond
601
     * @throws MetacatException when the metacat server generates another error
602
     */
603
    public String setAccess(String _docid, String _principal, String
604 3285 barteau
            _permission, String _permType,
605
            String _permOrder )
606
            throws InsufficientKarmaException, MetacatException,
607
            MetacatInaccessibleException {
608 2326 harris
        //set up properties
609
        Properties prop = new Properties();
610
        prop.put("action", "setaccess");
611
        prop.put("docid", _docid);
612
        prop.put("principal", _principal);
613
        prop.put("permission", _permission);
614
        prop.put("permType", _permType);
615
        prop.put("permOrder", _permOrder);
616 3285 barteau
617 2326 harris
        String response = null;
618
        try {
619
            response = sendDataForString(prop, null, null, 0);
620
        } catch (Exception e) {
621
            throw new MetacatInaccessibleException(e.getMessage());
622
        }
623 3285 barteau
624 2326 harris
        // Check for an error condition
625
        if (response.indexOf("<error>") != -1) {
626
            if (response.indexOf("does not have permission") != -1) {
627
                throw new InsufficientKarmaException(response);
628
            } else {
629
                throw new MetacatException(response);
630
            }
631
        }
632 1795 jones
        return response;
633 1780 jones
    }
634 3285 barteau
635 1780 jones
    /**
636
     * When the MetacatFactory creates an instance it needs to set the
637
     * MetacatUrl to which connections should be made.
638
     *
639
     * @param metacatUrl the URL for the metacat server
640
     */
641 3285 barteau
    public void setMetacatUrl(String metacatUrl) {
642 1783 jones
        this.metacatUrl = metacatUrl;
643 1780 jones
    }
644 3285 barteau
645 1822 jones
    /**
646
     * Get the session identifier for this session.  This is only valid if
647
     * the login methods has been called successfully for this Metacat object
648
     * beforehand.
649
     *
650
     * @returns the sessionId as a String, or null if the session is invalid
651
     */
652 3285 barteau
    public String getSessionId() {
653 1822 jones
        return this.sessionId;
654
    }
655 3285 barteau
656 1826 jones
    /**
657 2240 sgarg
     * Set the session identifier for this session.  This identifier was
658
     * previously established with a call to login.  To continue to use the
659 1826 jones
     * same session, set the session id before making a call to one of the
660
     * metacat access methods (e.g., read, query, insert, etc.).
661
     *
662
     * @param String the sessionId from a previously established session
663
     */
664 3285 barteau
    public void setSessionId(String sessionId) {
665 1826 jones
        this.sessionId = sessionId;
666
    }
667 2337 tao
668
    /**
669 3285 barteau
     * The method will return the latest revision in metacat server
670 2981 jones
     * for a given document id. If some error happens, this method will throw
671 3285 barteau
     * an exception.
672 2337 tao
     * @param docId String  the given docid you want to use. the docid it self
673
     *                      can have or haven't revision number
674
     * @throws MetacatException
675
     */
676 3285 barteau
    public int getNewestDocRevision(String docId) throws MetacatException {
677
        int rev = 0;
678
        //set up properties
679
        Properties prop = new Properties();
680
        prop.put("action", "getrevisionanddoctype");
681
        prop.put("docid", docId);
682
683
        String response = null;
684
        try {
685
            response = sendDataForString(prop, null, null, 0);
686
            //parseRevisionResponse will return null if there is an
687
            //error that it can't handle
688
            String revStr = parserRevisionResponse(response);
689
            Integer revObj = new Integer(revStr);
690
            rev = revObj.intValue();
691
            // Check for an error condition
692
            if (response.indexOf("<error>") != -1 && revStr == null) {
693
                throw new MetacatException(response);
694
            }
695
        } catch (Exception e) {
696
            throw new MetacatException(e.getMessage());
697
        }
698
        return rev;
699
    }
700
701 2981 jones
    /**
702
     * Return the highest document id for a given scope.  This is used by
703
     * clients to make it easier to determine the next free identifier in a
704 3285 barteau
     * sequence for a given scope.
705 2981 jones
     * @param scope String  the scope to use for looking up the latest id
706
     * @throws MetacatException when an error occurs
707
     */
708
    public String getLastDocid(String scope) throws MetacatException {
709
        String lastIdentifier = "";
710
        //set up properties
711
        Properties prop = new Properties();
712
        prop.put("action", "getlastdocid");
713
        prop.put("scope", scope);
714 3285 barteau
715 2981 jones
        String response = null;
716
        try {
717 2337 tao
            response = sendDataForString(prop, null, null, 0);
718
            // Check for an error condition
719 2981 jones
            if (response.indexOf("<error>") != -1) {
720 3285 barteau
                throw new MetacatException(response);
721 2981 jones
            } else {
722
                Reader responseReader = new StringReader(response);
723 3285 barteau
                Node root =
724
                        XMLUtilities.getXMLReaderAsDOMTreeRootNode(responseReader);
725
                Node docidNode =
726
                        XMLUtilities.getNodeWithXPath(root, "/lastDocid/docid");
727 2986 jones
                lastIdentifier = docidNode.getFirstChild().getNodeValue();
728 2981 jones
            }
729
        } catch (Exception e) {
730 2337 tao
            throw new MetacatException(e.getMessage());
731
        }
732 2981 jones
        return lastIdentifier;
733
    }
734 3141 berkley
735
    /**
736
     * return a list of all docids that match a given scope.  if scope is null
737
     * return all docids registered in the system
738
     * @param scope String  the scope to use to limit the docid query
739
     * @throws MetacatException when an error occurs
740
     */
741
    public Vector getAllDocids(String scope) throws MetacatException {
742
        Vector resultVec = new Vector();
743
        //set up properties
744
        Properties prop = new Properties();
745
        prop.put("action", "getalldocids");
746 3285 barteau
        if(scope != null) {
747
            prop.put("scope", scope);
748 3141 berkley
        }
749 3285 barteau
750 3141 berkley
        String response = null;
751
        try {
752
            response = sendDataForString(prop, null, null, 0);
753
            // Check for an error condition
754
            if (response.indexOf("<error>") != -1) {
755 3285 barteau
                throw new MetacatException(response);
756 3141 berkley
            } else {
757
                Reader responseReader = new StringReader(response);
758 3285 barteau
                Node root =
759
                        XMLUtilities.getXMLReaderAsDOMTreeRootNode(responseReader);
760 3141 berkley
                NodeList nlist = root.getChildNodes();
761 3285 barteau
                for(int i=0; i<nlist.getLength(); i++) {
762
                    Node n = nlist.item(i);
763
                    if(n.getNodeName().equals("docid")) {
764
                        //add the content to the return vector
765
                        String nodeVal = n.getFirstChild().getNodeValue();
766
                        resultVec.addElement(nodeVal);
767
                    }
768 3141 berkley
                }
769
770
            }
771
        } catch (Exception e) {
772
            throw new MetacatException(e.getMessage());
773
        }
774
        return resultVec;
775
    }
776 3143 berkley
777
    /**
778
     * return true of the given docid is registered, false if not
779
     * @param scope String  the scope to use to limit the docid query
780
     * @throws MetacatException when an error occurs
781
     */
782
    public boolean isRegistered(String docid) throws MetacatException {
783
        Vector resultVec = new Vector();
784
        //set up properties
785
        Properties prop = new Properties();
786
        prop.put("action", "isregistered");
787 3285 barteau
        if(docid == null) {
788
            throw new MetacatException("<error>Cannot check if a null docid " +
789
                    "is registered.</error>");
790 3143 berkley
        }
791
        prop.put("docid", docid);
792 3285 barteau
793 3143 berkley
        String response = null;
794
        try {
795
            response = sendDataForString(prop, null, null, 0);
796
            // Check for an error condition
797
            if (response.indexOf("<error>") != -1) {
798 3285 barteau
                throw new MetacatException(response);
799 3143 berkley
            } else {
800
                Reader responseReader = new StringReader(response);
801
                StringBuffer sb = new StringBuffer();
802
                char[] c = new char[1024];
803
                int numread = responseReader.read(c, 0, 1024);
804 3285 barteau
                while(numread != -1) {
805
                    sb.append(new String(c, 0, numread));
806
                    numread = responseReader.read(c, 0, 1024);
807 3143 berkley
                }
808
809
                String responseStr = sb.toString();
810 3285 barteau
                if(responseStr.indexOf("true") != -1) {
811
                    return true;
812 3143 berkley
                }
813
                return false;
814
            }
815
        } catch (Exception e) {
816
            throw new MetacatException(e.getMessage());
817
        }
818
    }
819 3285 barteau
820 1780 jones
    /************************************************************************
821
     * PRIVATE METHODS
822
     ************************************************************************/
823 3285 barteau
824 1783 jones
    /**
825
     * Send a request to metacat.
826
     *
827
     * @param prop the properties to be URL encoded and sent
828 2264 sgarg
     * @param filename  the properties to be sent to Metacat
829
     *                  in case of upload, otherwise null
830
     * @param fileData  the inputStream for the file data to be sent to Metacat
831
     *                  in case of upload, otherwise null
832
     * @param size      the size of the data being sent to Metacat
833
     *                  in case of upload, otherwise 0
834 1783 jones
     */
835 2240 sgarg
    synchronized private InputStream sendDataOnce(Properties args,
836 3285 barteau
            Properties filename,
837
            InputStream fileData,
838
            int size)
839
            throws Exception {
840 1780 jones
        InputStream returnStream = null;
841
        URL url = new URL(metacatUrl);
842
        HttpMessage msg = new HttpMessage(url);
843 1828 jones
        msg.setCookie("JSESSIONID="+this.sessionId);
844 2264 sgarg
        if (filename == null){
845
            returnStream = msg.sendPostData(args);
846
        } else if (fileData == null){
847
            returnStream = msg.sendPostData(args, filename);
848
        } else if (size > 0) {
849
            returnStream = msg.sendPostData(args, filename, fileData, size);
850 2240 sgarg
        } else {
851 2264 sgarg
            throw new MetacatException("Invalid size specified for " +
852 3285 barteau
                    "the input stream being passed");
853 2240 sgarg
        }
854 1780 jones
        return returnStream;
855
    }
856 3285 barteau
857 1780 jones
    /**
858
     * Send a request to Metacat
859
     *
860 2264 sgarg
     * @param args  the properties to be sent to Metacat
861
     * @param filename  the properties to be sent to Metacat
862
     *                  in case of upload, otherwise null
863
     * @param fileData  the inputStream for the file data to be sent to Metacat
864
     *                  in case of upload, otherwise null
865
     * @param size      the size of the data being sent to Metacat
866
     *                  in case of upload, otherwise 0
867 1780 jones
     * @return      InputStream as returned by Metacat
868
     */
869 2240 sgarg
    synchronized private InputStream sendData(Properties args,
870 3285 barteau
            Properties filename,
871
            InputStream fileData,
872
            int size)
873
            throws Exception {
874 1780 jones
        InputStream returnStream = null;
875
        /*
876
            Note:  The reason that there are three try statements all executing
877
            the same code is that there is a problem with the initial connection
878 2240 sgarg
            using the HTTPClient protocol handler.  These try statements make
879
            sure that a connection is made because it gives each connection a
880 1780 jones
            2nd and 3rd chance to work before throwing an error.
881
            THIS IS A TOTAL HACK.  THIS NEEDS TO BE LOOKED INTO AFTER THE BETA1
882
            RELEASE OF MORPHO!!!  cwb (7/24/01)
883 3285 barteau
         */
884 1780 jones
        try {
885 3285 barteau
            return sendDataOnce(args, filename, fileData, size);
886 1780 jones
        } catch (Exception e) {
887
            try {
888 2264 sgarg
                return sendDataOnce(args, filename, fileData, size);
889 1780 jones
            } catch (Exception e2) {
890
                try {
891 2264 sgarg
                    return sendDataOnce(args, filename, fileData, size);
892 1780 jones
                } catch (Exception e3) {
893
                    System.err.println(
894 3196 berkley
                            "Failed to send data to metacat 3 times: " + e3.getMessage());
895
                    System.err.println("metacaturl: " + metacatUrl);
896 1780 jones
                    throw e3;
897
                }
898
            }
899
        }
900
    }
901 3285 barteau
902 1783 jones
    /**
903
     * Send a request to Metacat
904
     *
905 2264 sgarg
     * @param args      the properties to be sent to Metacat
906
     * @param filename  the properties to be sent to Metacat
907
     *                  in case of upload, otherwise null
908
     * @param fileData  the inputStream for the file data to be sent to Metacat
909
     *                  in case of upload, otherwise null
910
     * @param size      the size of the data being sent to Metacat
911
     *                  in case of upload, otherwise 0
912
     * @return          a string as returned by Metacat
913 1783 jones
     */
914 2240 sgarg
    synchronized private String sendDataForString(Properties args,
915 3285 barteau
            Properties filename,
916
            InputStream fileData,
917
            int size)
918
            throws Exception {
919 1783 jones
        String response = null;
920 3285 barteau
921 1783 jones
        try {
922
            InputStreamReader returnStream =
923 2264 sgarg
                    new InputStreamReader(sendData(args, filename,
924 3285 barteau
                    fileData, size));
925 1783 jones
            StringWriter sw = new StringWriter();
926
            int len;
927
            char[] characters = new char[512];
928
            while ((len = returnStream.read(characters, 0, 512)) != -1) {
929
                sw.write(characters, 0, len);
930
            }
931
            returnStream.close();
932
            response = sw.toString();
933
            sw.close();
934
        } catch (Exception e) {
935
            throw e;
936
        }
937
        return response;
938
    }
939 2337 tao
940
    /*
941
     * "getversionanddoctype" action will return a string from metacat server.
942
     * The string format is "revision;doctype"(This is bad idea, we should use xml)
943
     * This method will get revision string from the response string
944
     */
945 3285 barteau
    private String parserRevisionResponse(String response) throws Exception {
946
        String revision = null;
947
        if (response != null) {
948
            if(response.indexOf("<error>") != -1) {
949
                if(response.indexOf("There is not record") != -1) {
950
                    return "0";
951
                } else {
952
                    return null;
953
                }
954
            } else {
955
                int firstSemiCol = response.indexOf(";");
956
                revision = response.substring(0, firstSemiCol);
957
            }
958 2992 berkley
        }
959 3285 barteau
        return revision;
960
    }
961
962
    /**
963
     * JSP API: This is a convenience method to reduce the amount of code in a Metacat Client
964
     * JSP.  It handles creating/reusing an instance of a MetacatClient.
965
     * @param request Since this is intended to be used by a JSP, it is passed the
966
     * available "request" variable (the HttpServletRequest).
967
     * @throws edu.ucsb.nceas.metacat.client.MetacatInaccessibleException Received by MetacatFactory.
968
     * @return MetacatClient instance.
969
     */
970
    public static MetacatClient getMetacatClient(javax.servlet.http.HttpServletRequest request) throws MetacatInaccessibleException {
971
        MetacatClient                       result;
972
        String                              metacatPath = "http://%1$s%2$s/metacat";
973
        String                              host, context;
974
        javax.servlet.http.HttpSession      session;
975
976
        session = request.getSession();
977
        result = (MetacatClient) session.getAttribute("MetacatClient");
978
        if (result == null) {
979
            host = request.getHeader("host");
980
            context = request.getContextPath();
981
            metacatPath = String.format(metacatPath, host, context);
982
            result = (MetacatClient) MetacatFactory.createMetacatConnection(metacatPath);
983
            session.setAttribute("MetacatClient", result);
984
        }
985
        return(result);
986
    }
987
988
    /**
989
     * JSP API: When the user logs in, the server will send back a string containing XML.  Calling
990
     * this method with the string will allow other methods to work, such as isLoggIn()
991
     * and getLoginResponseElement().
992
     * @param xmlString XML in String format.
993
     * @throws java.io.IOException Input/Output exception.
994
     */
995
    public void setLoginResponse(String xmlString) throws IOException {
996
        if (xmlString != null) {
997
            loginResponse = XMLUtilities.getXMLReaderAsDOMDocument(new StringReader(xmlString));
998
        }
999
    }
1000
1001
    private void setMetadataDoc(InputStream ioStream) throws IOException {
1002
        BufferedReader                          buffy;
1003
1004
        if (ioStream != null) {
1005
            buffy = new BufferedReader(new InputStreamReader(ioStream));
1006
            metadataDoc = XMLUtilities.getXMLReaderAsDOMDocument(buffy);
1007
        }
1008
    }
1009
1010
    /**
1011
     * JSP API: A convenient and efficient method to retrieve info from the "login response".
1012
     * @param elementName String of the elementName.
1013
     * NOTE: setLoginResponse() must have been called first,
1014
     * otherwise it will always return null.
1015
     * @throws javax.xml.xpath.XPathExpressionException XPath error.
1016
     * @return String containing the text content of the element, or null.
1017
     */
1018
    public String getLoginResponseElement(String elementName) throws XPathExpressionException {
1019
        String                      result = null;
1020
1021
        if (loginResponse != null) {
1022
            result = (String) xpath.evaluate(elementName, loginResponse.getDocumentElement(), XPathConstants.STRING);
1023
            if (result != null)
1024
                result = result.trim();
1025
        }
1026
        return(result);
1027
    }
1028
1029
1030
    /**
1031
     * JSP API: Easy way to get info from an uploaded metadata XML file.
1032
     * Note:  doMetadataUpload() must have been called first.
1033
     * @param elementName String containing the elemement name
1034
     * @throws javax.xml.xpath.XPathExpressionException Thrown by XPath
1035
     * @return String text content of the named element
1036
     */
1037
    public String getMetadataDocElement(String elementName) throws XPathExpressionException {
1038
        String                      result = null;
1039
1040
        if (metadataDoc != null) {
1041
            result = (String) xpath.evaluate(elementName, metadataDoc.getDocumentElement(), XPathConstants.STRING);
1042
            result = result.trim();
1043
        }
1044
        return(result);
1045
    }
1046
1047
    /**
1048
     * JSP API: A convenience method to be used by JSP or any other client code that requires
1049
     * the user to be logged in.  NOTE: setUser() must have been called first,
1050
     * otherwise it will always return false.
1051
     * @return boolean  true if user has logged in for this session, false otherwise.
1052
     */
1053
    public boolean isLoggedIn() {
1054
        return(user != null);
1055
    }
1056
1057
    /**
1058
     * JSP API: After calling "login(ldapUserName, pwd)", call this with the username
1059
     * and servers response message.  You can than use isLoggedIn() to determine if
1060
     * the user is logged in, getLoginResponseElement(), etc.  The user name will also
1061
     * used by calls to doMetadataUpload() for Document Id creation (scope).
1062
     * @param userName User name
1063
     * @param serverResponse XML login response sent from Metacat.
1064
     */
1065
    public void setUser(String userName, String serverResponse) {
1066
        if (serverResponse != null && serverResponse.contains("login"))
1067
            user = userName;
1068 2992 berkley
        else
1069 3285 barteau
            user = null;
1070
    }
1071
1072
    /**
1073
     * JSP API:  Handles metadata file and data file uploads for inserting new
1074
     * Metacat data packages.  Note: if content type is not "multipart/form-data",
1075
     * nothing will happen; thus, it's safe to be (unintentionally) called by other
1076
     * types of form submissions.
1077
     * @param request HTTP request.
1078
     * @return A 1-line status message for the user.
1079
     */
1080
    public String doMetadataUpload(javax.servlet.http.HttpServletRequest request) {
1081
        String                      result = "", contentType, formatType;
1082
        String                      lastDocId, nextDocId, metaDocId;
1083
        StringBuilder               fileName = new StringBuilder();
1084
        Reader                      reader;
1085
        int                         sizeLimit;
1086
        MultipartParser             multipartParser;
1087
        InputStream                 inputStream;
1088
        Node                        newBranch, metaRootNode;
1089
        HashMap                     dataDocIDs;
1090
1091
        //*** Only process request if a file upload.
1092
        contentType = request.getContentType();
1093
        if (isLoggedIn() && contentType != null && contentType.contains("multipart/form-data")) {
1094
            try {
1095
                //*** Init the MultipartParser.
1096
                sizeLimit = (new Integer(MetaCatUtil.getOption("datafilesizelimit"))).intValue();
1097
                multipartParser = new MultipartParser(request, sizeLimit * 1024 * 1024);
1098
1099
                //*** Get the First file, which should be the metadata file.
1100
                inputStream = getNextInputStream(multipartParser, fileName);
1101
                if (fileName.toString().toLowerCase().endsWith(".xml")) {
1102
                    setMetadataDoc(inputStream);
1103
1104
                    //*** Get the Metadata File's DOC ID.
1105
                    lastDocId = getLastDocid(user);
1106
                    metaDocId = lastDocId = nextDocId(lastDocId);
1107
1108
                    if (isFGDC()) {
1109
                        //*** Loop thru all of the data files, get fileName and inputStream.
1110
                        dataDocIDs = new HashMap();
1111
                        fileName = new StringBuilder();
1112
                        while ((inputStream = getNextInputStream(multipartParser, fileName)) != null) {
1113
                            //*** Get the data file's DOC ID.
1114
                            nextDocId = nextDocId(lastDocId);
1115
                            //*** Set the file format (just using file extension for now).
1116
                            formatType = fileName.substring(fileName.lastIndexOf(".")+1).toUpperCase();
1117
                            dataDocIDs.put(nextDocId, formatType);
1118
                            //*** Upload the data file to metacat.
1119
                            upload(nextDocId, fileName.toString(), inputStream, sizeLimit);
1120
1121
                            lastDocId = nextDocId;
1122
                            fileName = new StringBuilder();
1123
                        }
1124
1125
                        //*** Store the User Name and Doc Id in the FGDC document.
1126
                        newBranch = getFGDCdisinfo(getLoginResponseElement("name"), metaDocId, dataDocIDs);
1127
                        System.out.println("MetacatClient.doMetadataUpload: " + XMLUtilities.getDOMTreeAsString(newBranch));
1128
                        metaRootNode = addDistInfoToFGDC(newBranch);
1129
1130
                        //*** Upload the metadata file to metacat.
1131
                        reader = XMLUtilities.getDOMTreeAsReader(metadataDoc.getDocumentElement(), false);
1132
                        insert(metaDocId, reader, null);
1133
1134
                        result = "MetaCat Package Inserted:  Metadata Doc ID #" + metaDocId;
1135
                        reader.close();
1136
                    } else {
1137
                        System.out.println("MetacatClient.doUpload: not an FGDC file = " + fileName);
1138
                        result = fileName + " is not an FGDC file.  Files not uploaded.";
1139
                        //TODO add other types of metadata grammars here...
1140
                    }
1141
                } else {
1142
                    result = "The first file must be an XML Metadata file.  Files not uploaded.";
1143
                }
1144
                if (inputStream != null)
1145
                    inputStream.close();
1146
            } catch (MetacatException ex)  {
1147
                result = ex.getMessage();
1148
                System.out.println("MetacatClient.doUpload: MetacatException = " + result);
1149
            } catch (IOException ex)  {
1150
                System.out.println("MetacatClient.doUpload: " + ex);
1151
            } catch (Exception ex) {
1152
                System.out.println("MetacatClient.doUpload: " + ex);
1153
            } catch (Error err) {
1154
                System.out.println("MetacatClient.doUpload: ERR - " + err.getCause());
1155
                result = "ERR: " + err.getMessage();
1156
            }
1157 2992 berkley
        }
1158 3285 barteau
        return(result);
1159 2337 tao
    }
1160 3285 barteau
1161
    private InputStream getNextInputStream(MultipartParser multipartParser, StringBuilder fileName) throws IOException {
1162
        InputStream                     result = null;
1163
        Part                            part;
1164
        String                          parmName = null, value = null, fnam;
1165
1166
        while ((part = multipartParser.readNextPart()) != null) {
1167
            if (part.isParam()) {
1168
                parmName = part.getName();
1169
                value = ((ParamPart) part).getStringValue();
1170
                System.out.println("MetacatClient.doUpload: parmName = " + parmName + "  value = " + value);
1171
1172
            } else if (part.isFile()) {
1173
                fnam = ((FilePart) part).getFileName();
1174
                if (fnam != null && !fnam.equals("")) {
1175
                    //*** File name is passed back via StringBuilder fileName param.
1176
                    fileName.append(fnam);
1177
                    result = ((FilePart) part).getInputStream();
1178
                    System.out.println("MetacatClient.doUpload: fileName = " + fileName + "  inputStream = " + result.toString());
1179
                    break;
1180
                }
1181
            }
1182
        }
1183
        return(result);
1184
    }
1185
1186
    private String nextDocId(String lastDocId) {
1187
        String                      result = null, tokens[];
1188
        int                         vers;
1189
        String                      template = user.toLowerCase() + ".%1$d.%2$d";
1190
1191
        if(lastDocId != null && lastDocId.contains(".")) {
1192
            lastDocId = lastDocId.replace('.','~'); //*** This is necessary for the split to work.
1193
            tokens = lastDocId.split("~");
1194
            if(tokens.length > 1 && !tokens[1].equals("")) {
1195
                try {
1196
                    vers = Integer.parseInt(tokens[1]);
1197
                    result = String.format(template, 1 + vers, 1);
1198
                } catch (NumberFormatException ex) {
1199
                    //*** In case the lastDocId has something other than a number.
1200
                    result = String.format(template, 1, 1);
1201
                }
1202
            } else {
1203
                //*** In case the lastDocId ends with a '.'
1204
                result = String.format(template, 1, 1);
1205
            }
1206
        } else {
1207
            //*** In case there isn't any doc Id's with the user name.
1208
            result = String.format(template, 1, 1);
1209
        }
1210
        return(result);
1211
    }
1212
1213
    private boolean isFGDC() {
1214
        boolean                     result = false;
1215
        DocumentType                docType;
1216
        String                      sysId, title = null;
1217
        final String                FGDC_TEST_EXPRESSION = "/metadata/idinfo/citation/citeinfo/title";
1218
1219
        //*** First, try the rigid proper way of determining it.
1220
        if (metadataDoc != null) {
1221
            docType = metadataDoc.getDoctype();
1222
            if (docType != null) {
1223
                sysId = docType.getSystemId();
1224
                if (sysId != null)
1225
                    result = sysId.contains(FGDC_SYSTEM_ID);
1226
            }
1227
        }
1228
        //*** It might not have a doc type line, so try another method.
1229
        if (!result) {
1230
            try {
1231
                title = getMetadataDocElement(FGDC_TEST_EXPRESSION);
1232
            } catch (XPathExpressionException ex) {
1233
                ex.printStackTrace();
1234
            }
1235
            result = (title != null && !title.equals(""));
1236
        }
1237
        return(result);
1238
    }
1239
1240
    private Node getFGDCdisinfo(String contactName, String resourceDescription, HashMap dataDocIDs) throws IOException {
1241
        Node                        result = null, node, digformBranch, formname, stdorder;
1242
        Document                    doc;
1243
        Iterator                    iterIt;
1244
        String                      key, value;
1245
1246
        //*** This is a valid/minimal FGDC "distinfo" branch.
1247
        final String XML = "<distinfo>"
1248
                + "    <distrib>"
1249
                + "        <cntinfo>"
1250
                + "            <cntperp>"
1251
                + "                <cntper></cntper>"
1252
                + "            </cntperp>"
1253
                + "            <cntaddr>"
1254
                + "                <addrtype></addrtype>"
1255
                + "                <address></address>"
1256
                + "                <city></city>"
1257
                + "                <state></state>"
1258
                + "                <postal></postal>"
1259
                + "                <country></country>"
1260
                + "            </cntaddr>"
1261
                + "            <cntvoice></cntvoice>"
1262
                + "        </cntinfo>"
1263
                + "    </distrib>"
1264
                + "    <resdesc></resdesc>"
1265
                + "    <distliab></distliab>"
1266
                + "    <stdorder>"
1267
                + "        <digform>"
1268
                + "            <digtinfo>"
1269
                + "                <formname></formname>"
1270
                + "            </digtinfo>"
1271
                + "            <digtopt>"
1272
                + "                <onlinopt>"
1273
                + "                    <computer>"
1274
                + "                        <networka>"
1275
                + "                            <networkr></networkr>"
1276
                + "                        </networka>"
1277
                + "                    </computer>"
1278
                + "                </onlinopt>"
1279
                + "            </digtopt>"
1280
                + "        </digform>"
1281
                + "        <fees></fees>"
1282
                + "    </stdorder>"
1283
                + "</distinfo>";
1284
1285
        doc = XMLUtilities.getXMLReaderAsDOMDocument(new StringReader(XML));
1286
        result = doc.getDocumentElement();
1287
        try {
1288
            //*** Set the Contact Person.
1289
            node = (Node) xpath.evaluate("/distinfo/distrib/cntinfo/cntperp/cntper", result, XPathConstants.NODE);
1290
            node.setTextContent(contactName);
1291
            //*** Set the metadata Doc Id.
1292
            node = (Node) xpath.evaluate("/distinfo/resdesc", result, XPathConstants.NODE);
1293
            node.setTextContent(resourceDescription);
1294
1295
            //*** Loop thru the files, setting their format and Doc Id.
1296
            stdorder = (Node) xpath.evaluate("/distinfo/stdorder", result, XPathConstants.NODE);
1297
            digformBranch = (Node) xpath.evaluate("/distinfo/stdorder/digform", result, XPathConstants.NODE);
1298
            iterIt = dataDocIDs.keySet().iterator();
1299
            while(iterIt.hasNext()) {
1300
                //*** Save the data file Doc ID (required).
1301
                key = (String) iterIt.next();
1302
                node = (Node) xpath.evaluate("digtopt/onlinopt/computer/networka/networkr", digformBranch, XPathConstants.NODE);
1303
                node.setTextContent(key);
1304
                //*** Save the data file format (optional).
1305
                formname = (Node) xpath.evaluate("digtinfo/formname", digformBranch, XPathConstants.NODE);
1306
                if ((value = (String) dataDocIDs.get(key)) != null && !value.equals("")) {
1307
                    formname.setTextContent(value);
1308
                } else {
1309
                    //*** We did a deep clone of the branch, so clear prior contents.
1310
                    formname.setTextContent("");
1311
                }
1312
1313
                //*** Clone branch for next file.
1314
                if (iterIt.hasNext()) {
1315
                    digformBranch = digformBranch.cloneNode(true);
1316
                    stdorder.appendChild(digformBranch);
1317
                }
1318
            }
1319
        } catch (XPathExpressionException ex) {
1320
            ex.printStackTrace();
1321
        }
1322
        return(result);
1323
    }
1324
1325
    private Node addDistInfoToFGDC(Node newBranch) {
1326
        Node                        result = null, node;
1327
1328
        if (newBranch != null) {
1329
            result = metadataDoc.getDocumentElement();
1330
            try {
1331
                //*** Get a reference to the FGDC required "metainfo" node (only 1 allowed).
1332
                node = (Node) xpath.evaluate("/metadata/metainfo", result, XPathConstants.NODE);
1333
                if (node != null) {
1334
                    newBranch = metadataDoc.importNode(newBranch, true);
1335
                    //*** Add the new "distinfo" before it.
1336
                    result.insertBefore(newBranch, node);
1337
                }
1338
            } catch (XPathExpressionException ex) {
1339
                ex.printStackTrace();
1340
            }
1341
        }
1342
        return(result);
1343
    }
1344
1345 1780 jones
}