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
import java.io.InputStream;
28 1783 jones
import java.io.InputStreamReader;
29 1784 jones
import java.io.PushbackReader;
30 2981 jones
import java.io.StringReader;
31 1784 jones
import java.io.IOException;
32 1783 jones
import java.io.StringWriter;
33 1780 jones
import java.io.Reader;
34
import java.net.URL;
35 3481 barteau
import java.util.HashMap;
36 1780 jones
import java.util.Properties;
37 3141 berkley
import java.util.Vector;
38 3300 barteau
import javax.servlet.http.HttpServletRequest;
39 3285 barteau
import javax.xml.xpath.XPath;
40
import javax.xml.xpath.XPathFactory;
41
import org.w3c.dom.Document;
42 1780 jones
43 2981 jones
import org.w3c.dom.Node;
44 3141 berkley
import org.w3c.dom.NodeList;
45 2981 jones
46 1780 jones
import edu.ucsb.nceas.utilities.HttpMessage;
47 1788 jones
import edu.ucsb.nceas.utilities.IOUtil;
48 2981 jones
import edu.ucsb.nceas.utilities.XMLUtilities;
49 2240 sgarg
import java.io.File;
50 1780 jones
51
/**
52 2240 sgarg
 *  This interface provides methods for initializing and logging in to a
53
 *  Metacat server, and then querying, reading, transforming, inserting,
54 1780 jones
 *  updating and deleting documents from that server.
55
 */
56 3285 barteau
public class MetacatClient implements Metacat {
57 1780 jones
    /** The URL string for the metacat server */
58
    private String metacatUrl;
59 3285 barteau
60 1822 jones
    /** The session identifier for the session */
61
    private String sessionId;
62 3285 barteau
63 3300 barteau
    /**
64 1780 jones
     * Constructor to create a new instance. Protected because instances
65
     * should only be created by the factory MetacatFactory.
66
     */
67 3285 barteau
    protected MetacatClient() {
68 1822 jones
        this.metacatUrl = null;
69
        this.sessionId = null;
70 1780 jones
    }
71 3285 barteau
72 1780 jones
    /**
73
     *  Method used to log in to a metacat server. Implementations will need
74
     *  to cache a cookie value to make the session persistent.  Each time a
75
     *  call is made to one of the other methods (e.g., read), the cookie will
76
     *  need to be passed back to the metacat server along with the request.
77
     *
78
     *  @param username   the username of the user, like an LDAP DN
79
     *  @param password   the password for that user for authentication
80 1822 jones
     *  @return the response string from metacat in XML format
81 1780 jones
     *  @throws MetacatAuthException when the username/password could
82
     *                    not be authenticated
83
     */
84 2240 sgarg
    public String login(String username, String password)
85 3285 barteau
    throws MetacatAuthException, MetacatInaccessibleException {
86 1783 jones
        Properties prop = new Properties();
87
        prop.put("action", "login");
88
        prop.put("qformat", "xml");
89
        prop.put("username", username);
90
        prop.put("password", password);
91 3285 barteau
92 1783 jones
        String response = null;
93
        try {
94 2264 sgarg
            response = sendDataForString(prop, null, null, 0);
95 1783 jones
        } catch (Exception e) {
96
            throw new MetacatInaccessibleException(e.getMessage());
97
        }
98 3285 barteau
99 1783 jones
        if (response.indexOf("<login>") == -1) {
100 1828 jones
            setSessionId("");
101 1783 jones
            throw new MetacatAuthException(response);
102 1822 jones
        } else {
103 1825 jones
            int start = response.indexOf("<sessionId>") + 11;
104 1822 jones
            int end = response.indexOf("</sessionId>");
105
            if ((start != -1) && (end != -1)) {
106 1828 jones
                setSessionId(response.substring(start,end));
107 1822 jones
            }
108 1783 jones
        }
109 1822 jones
        return response;
110 1780 jones
    }
111 2683 sgarg
112
    /**
113
     *  Method used to log in to a metacat server. Implementations will need
114
     *  to cache a cookie value to make the session persistent.  Each time a
115
     *  call is made to one of the other methods (e.g., read), the cookie will
116
     *  need to be passed back to the metacat server along with the request.
117
     *
118
     *  @param username   the username of the user, like an LDAP DN
119
     *  @param password   the password for that user for authentication
120
     *  @return the response string from metacat in XML format
121
     *  @throws MetacatAuthException when the username/password could
122
     *                    not be authenticated
123
     */
124 3285 barteau
    public String getloggedinuserinfo() throws MetacatInaccessibleException {
125 2683 sgarg
        Properties prop = new Properties();
126
        prop.put("action", "getloggedinuserinfo");
127
        prop.put("qformat", "xml");
128 3285 barteau
129 2683 sgarg
        String response = null;
130
        try {
131
            response = sendDataForString(prop, null, null, 0);
132
        } catch (Exception e) {
133
            throw new MetacatInaccessibleException(e.getMessage());
134
        }
135 3285 barteau
136 2683 sgarg
        return response;
137
    }
138 3285 barteau
139 1780 jones
    /**
140 1822 jones
     *  Method used to log out a metacat server. The Metacat server will end
141
     *  the session when this call is invoked.
142 1798 tao
     *
143 1822 jones
     *  @return the response string from metacat in XML format
144 1798 tao
     *  @throws MetacatInaccessibleException when the metacat server can not be
145
     *                                    reached or does not respond
146
     */
147 3285 barteau
    public String logout() throws MetacatInaccessibleException, MetacatException {
148 1798 tao
        Properties prop = new Properties();
149
        prop.put("action", "logout");
150 2240 sgarg
        prop.put("qformat", "xml");
151 3285 barteau
152 1798 tao
        String response = null;
153
        try {
154 2264 sgarg
            response = sendDataForString(prop, null, null, 0);
155 1798 tao
        } catch (Exception e) {
156
            throw new MetacatInaccessibleException(e.getMessage());
157
        }
158 3285 barteau
159 1798 tao
        if (response.indexOf("<logout>") == -1) {
160
            throw new MetacatException(response);
161
        }
162 1828 jones
        setSessionId("");
163 1822 jones
        return response;
164 1798 tao
    }
165 3285 barteau
166 1798 tao
    /**
167 1780 jones
     * Read an XML document from the metacat server session, accessed by docid,
168
     * and returned as a Reader.
169
     *
170
     * @param docid the identifier of the document to be read
171
     * @return a Reader for accessing the document
172 2240 sgarg
     * @throws InsufficientKarmaException when the user has insufficent rights
173 1780 jones
     *                                    for the operation
174 1784 jones
     * @throws MetacatInaccessibleException when the metacat server can not be
175
     *                                    reached or does not respond
176
     * @throws MetacatException when the metacat server generates another error
177 1780 jones
     */
178 1784 jones
    public Reader read(String docid) throws InsufficientKarmaException,
179 3285 barteau
            MetacatInaccessibleException, MetacatException, DocumentNotFoundException {
180 1784 jones
        PushbackReader pbr = null;
181 3285 barteau
182 1784 jones
        Properties prop = new Properties();
183
        prop.put("action", "read");
184
        prop.put("qformat", "xml");
185
        prop.put("docid", docid);
186
        InputStream response = null;
187
        try {
188 2264 sgarg
            response = sendData(prop, null, null, 0);
189 1784 jones
        } catch (Exception e) {
190
            throw new MetacatInaccessibleException(e.getMessage());
191
        }
192
        pbr = new PushbackReader(new InputStreamReader(response), 512);
193
        try {
194
            char[] characters = new char[512];
195
            int len = pbr.read(characters, 0, 512);
196
            StringWriter sw = new StringWriter();
197
            sw.write(characters, 0, len);
198
            String message = sw.toString();
199
            sw.close();
200
            pbr.unread(characters, 0, len);
201
            if (message.indexOf("<error>") != -1) {
202
                if (message.indexOf("does not have permission") != -1) {
203
                    throw new InsufficientKarmaException(message);
204 2989 berkley
                } else if(message.indexOf("does not exist") != -1) {
205
                    throw new DocumentNotFoundException(message);
206 1784 jones
                } else {
207
                    throw new MetacatException(message);
208
                }
209
            }
210
        } catch (IOException ioe) {
211
            throw new MetacatException(
212 2240 sgarg
                    "MetacatClient: Error converting Reader to String."
213 1784 jones
                    + ioe.getMessage());
214
        }
215
        return pbr;
216 1780 jones
    }
217 3285 barteau
218
219 1780 jones
    /**
220 3285 barteau
     * Read inline data from the metacat server session, accessed by
221
     * inlinedataid and returned as a Reader.
222
     *
223
     * @param inlinedataid the identifier of the data to be read
224
     * @return a Reader for accessing the document
225
     * @throws InsufficientKarmaException when the user has insufficent rights
226
     *                                    for the operation
227
     * @throws MetacatInaccessibleException when the metacat server can not be
228
     *                                    reached or does not respond
229
     * @throws MetacatException when the metacat server generates another error
230
     */
231
    public Reader readInlineData(String inlinedataid)
232
    throws InsufficientKarmaException,
233
            MetacatInaccessibleException, MetacatException {
234
        PushbackReader pbr = null;
235
236
        Properties prop = new Properties();
237
        prop.put("action", "readinlinedata");
238
        prop.put("inlinedataid", inlinedataid);
239
240
        InputStream response = null;
241
        try {
242
            response = sendData(prop, null, null, 0);
243
        } catch (Exception e) {
244
            throw new MetacatInaccessibleException(e.getMessage());
245
        }
246
247
        pbr = new PushbackReader(new InputStreamReader(response), 512);
248
        try {
249
            char[] characters = new char[512];
250
            int len = pbr.read(characters, 0, 512);
251
            StringWriter sw = new StringWriter();
252
            sw.write(characters, 0, len);
253
            String message = sw.toString();
254
            sw.close();
255
            pbr.unread(characters, 0, len);
256
257
            if (message.indexOf("<error>") != -1) {
258
                if (message.indexOf("does not have permission") != -1) {
259
                    throw new InsufficientKarmaException(message);
260
                } else {
261
                    throw new MetacatException(message);
262
                }
263
            }
264
        } catch (IOException ioe) {
265
            throw new MetacatException(
266
                    "MetacatClient: Error converting Reader to String."
267
                    + ioe.getMessage());
268
        }
269
270
        return pbr;
271
    }
272
273 2261 sgarg
    /**
274 2240 sgarg
     * Query the metacat document store with the given metacat-compatible
275 3464 tao
     * query document and default qformat xml, and return the result set as a Reader.
276 1780 jones
     *
277
     * @param xmlQuery a Reader for accessing the XML version of the query
278
     * @return a Reader for accessing the result set
279
     */
280 1786 tao
    public Reader query(Reader xmlQuery) throws MetacatInaccessibleException,
281 3285 barteau
            IOException {
282 3464 tao
        String qformat = "xml";
283
        return query(xmlQuery, qformat);
284
    }
285
286
    /**
287
     * Query the metacat document store with the given metacat-compatible
288
     * query document and qformat, and return the result set as a Reader.
289
     *
290
     * @param xmlQuery a Reader for accessing the XML version of the query
291
     * @param qformat the format of return doc. It can be xml, knb, lter and etal.
292
     * @return a Reader for accessing the result set
293
     */
294
    public Reader query(Reader xmlQuery, String qformat) throws MetacatInaccessibleException,
295
            IOException {
296 1786 tao
        Reader reader = null;
297
        String query = null;
298 1788 jones
        try {
299 3285 barteau
            query = IOUtil.getAsString(xmlQuery, true);
300 1788 jones
        } catch (IOException ioE) {
301 3285 barteau
            throw ioE;
302 1786 tao
        }
303 3285 barteau
304 1786 tao
        //set up properties
305
        Properties prop = new Properties();
306
        prop.put("action", "squery");
307 3464 tao
        prop.put("qformat", qformat);
308 1786 tao
        prop.put("query", query);
309 3285 barteau
310 1786 tao
        InputStream response = null;
311
        try {
312 2264 sgarg
            response = sendData(prop, null, null, 0);
313 1786 tao
        } catch (Exception e) {
314
            throw new MetacatInaccessibleException(e.getMessage());
315
        }
316
        reader = new InputStreamReader(response);
317
        return reader;
318 1780 jones
    }
319 3285 barteau
320 1780 jones
    /**
321
     * Insert an XML document into the repository.
322
     *
323
     * @param docid the docid to insert the document
324
     * @param xmlDocument a Reader for accessing the XML document to be inserted
325 2240 sgarg
     * @param schema a Reader for accessing the DTD or XML Schema for
326 1780 jones
     *               the document
327 1789 jones
     * @return the metacat response message
328 2240 sgarg
     * @throws InsufficientKarmaException when the user has insufficent rights
329 1780 jones
     *                                    for the operation
330 1789 jones
     * @throws MetacatInaccessibleException when the metacat server can not be
331
     *                                    reached or does not respond
332
     * @throws MetacatException when the metacat server generates another error
333
     * @throws IOException when there is an error reading the xml document
334 1780 jones
     */
335 1789 jones
    public String insert(String docid, Reader xmlDocument, Reader schema)
336 4296 daigle
    	throws InsufficientKarmaException, MetacatException, IOException,
337 3285 barteau
            MetacatInaccessibleException {
338 4296 daigle
339 1789 jones
        Reader reader = null;
340
        String doctext = null;
341
        String schematext = null;
342
        try {
343 3285 barteau
            doctext = IOUtil.getAsString(xmlDocument, true);
344
            if (schema != null) {
345
                schematext = IOUtil.getAsString(schema, true);
346
            }
347 1789 jones
        } catch (IOException ioE) {
348 3285 barteau
            throw ioE;
349 1789 jones
        }
350 3285 barteau
351 1789 jones
        //set up properties
352
        Properties prop = new Properties();
353
        prop.put("action", "insert");
354
        prop.put("docid", docid);
355
        prop.put("doctext", doctext);
356
        if (schematext != null) {
357
            prop.put("dtdtext", schematext);
358
        }
359 4296 daigle
360
        if (sessionId != null) {
361
            prop.put("sessionid", sessionId);
362
        }
363 3285 barteau
364 1789 jones
        String response = null;
365
        try {
366 2264 sgarg
            response = sendDataForString(prop, null, null, 0);
367 1789 jones
        } catch (Exception e) {
368
            throw new MetacatInaccessibleException(e.getMessage());
369
        }
370 3285 barteau
371 1789 jones
        // Check for an error condition
372
        if (response.indexOf("<error>") != -1) {
373
            if (response.indexOf("does not have permission") != -1) {
374
                throw new InsufficientKarmaException(response);
375
            } else {
376
                throw new MetacatException(response);
377
            }
378
        }
379 3285 barteau
380 1789 jones
        return response;
381 1780 jones
    }
382 3285 barteau
383 1780 jones
    /**
384
     * Update an XML document in the repository.
385
     *
386
     * @param docid the docid to update
387
     * @param xmlDocument a Reader for accessing the XML text to be updated
388 2240 sgarg
     * @param schema a Reader for accessing the DTD or XML Schema for
389 1780 jones
     *               the document
390 1795 jones
     * @return the metacat response message
391 2240 sgarg
     * @throws InsufficientKarmaException when the user has insufficent rights
392 1780 jones
     *                                    for the operation
393 1795 jones
     * @throws MetacatInaccessibleException when the metacat server can not be
394
     *                                    reached or does not respond
395
     * @throws MetacatException when the metacat server generates another error
396
     * @throws IOException when there is an error reading the xml document
397 1780 jones
     */
398 1795 jones
    public String update(String docid, Reader xmlDocument, Reader schema)
399 3285 barteau
    throws InsufficientKarmaException, MetacatException, IOException,
400
            MetacatInaccessibleException {
401 1795 jones
        Reader reader = null;
402
        String doctext = null;
403
        String schematext = null;
404
        try {
405 3285 barteau
            doctext = IOUtil.getAsString(xmlDocument, true);
406
            if (schema != null) {
407
                schematext = IOUtil.getAsString(schema, true);
408
            }
409 1795 jones
        } catch (IOException ioE) {
410 3285 barteau
            throw ioE;
411 1795 jones
        }
412 3285 barteau
413 1795 jones
        //set up properties
414
        Properties prop = new Properties();
415
        prop.put("action", "update");
416
        prop.put("docid", docid);
417
        prop.put("doctext", doctext);
418
        if (schematext != null) {
419
            prop.put("dtdtext", schematext);
420
        }
421 3285 barteau
422 1795 jones
        String response = null;
423
        try {
424 2264 sgarg
            response = sendDataForString(prop, null, null, 0);
425 1795 jones
        } catch (Exception e) {
426
            throw new MetacatInaccessibleException(e.getMessage());
427
        }
428 3285 barteau
429 1795 jones
        // Check for an error condition
430
        if (response.indexOf("<error>") != -1) {
431
            if (response.indexOf("does not have permission") != -1) {
432
                throw new InsufficientKarmaException(response);
433
            } else {
434
                throw new MetacatException(response);
435
            }
436
        }
437 3285 barteau
438 1795 jones
        return response;
439 1780 jones
    }
440 3285 barteau
441 1780 jones
    /**
442 3721 jones
     * Upload a data document into the repository. Data files are stored on
443
     * metacat and may be in any format (binary or text), but they are all
444
     * treated as if they were binary.  Data files are not searched by the
445
     * query() methods because they are not loaded into the XML store because
446
     * they are not XML documents.  The File parameter is used to determine a
447
     * name for the uploaded document.
448 3285 barteau
     *
449 3721 jones
     * @param docid the identifier to be used for the document
450
     * @param file the File to be uploaded
451
     * @param document a InputStream containing the data to be uploaded
452 3285 barteau
     * @return the metacat response message
453
     * @throws InsufficientKarmaException when the user has insufficent rights
454
     *                                    for the operation
455
     * @throws MetacatInaccessibleException when the metacat server can not be
456
     *                                    reached or does not respond
457
     * @throws MetacatException when the metacat server generates another error
458
     * @throws IOException when there is an error reading the xml document
459
     */
460
    public String upload(String docid, File file)
461
    throws InsufficientKarmaException, MetacatException, IOException,
462
            MetacatInaccessibleException {
463
464
        URL url = new URL(metacatUrl.trim());
465
        HttpMessage msg = new HttpMessage(url);
466
        //set up properties
467
        Properties arg = new Properties();
468
        arg.put("action", "upload");
469
        arg.put("docid", docid);
470
471
        Properties filenames = new Properties();
472
        String filename = file.getAbsolutePath();
473
        filenames.put("datafile", filename);
474
475
        String response = null;
476
        try {
477 2264 sgarg
            response = sendDataForString(arg, filenames, null, 0);
478 3285 barteau
        } catch (Exception e) {
479 2240 sgarg
            throw new MetacatInaccessibleException(e.getMessage());
480 3285 barteau
        }
481
482
        // Check for an error condition
483
        if (response.indexOf("<error>") != -1) {
484 2240 sgarg
            if (response.indexOf("does not have permission") != -1) {
485 3285 barteau
                throw new InsufficientKarmaException(response);
486 2240 sgarg
            } else {
487 3285 barteau
                throw new MetacatException(response);
488 2240 sgarg
            }
489 3285 barteau
        }
490
491
        return response;
492
    }
493
494
    /**
495 3721 jones
     * Upload a data document into the repository. Data files are stored on
496
     * metacat and may be in any format (binary or text), but they are all
497
     * treated as if they were binary.  Data files are not searched by the
498
     * query() methods because they are not loaded into the XML store because
499
     * they are not XML documents. The name for the document is set explicitly
500
     * using the filename parameter.
501 3285 barteau
     *
502 3721 jones
     * @param docid the identifier to be used for the document
503
     * @param filename the name to be used in the MIME description of the uploaded file
504
     * @param document a InputStream containing the data to be uploaded
505 3285 barteau
     * @return the metacat response message
506
     * @throws InsufficientKarmaException when the user has insufficent rights
507
     *                                    for the operation
508
     * @throws MetacatInaccessibleException when the metacat server can not be
509
     *                                    reached or does not respond
510
     * @throws MetacatException when the metacat server generates another error
511
     * @throws IOException when there is an error reading the xml document
512
     */
513
    public String upload(String docid, String filename, InputStream fileData,
514
            int size)
515
            throws InsufficientKarmaException, MetacatException, IOException,
516
            MetacatInaccessibleException {
517
518
        URL url = new URL(metacatUrl.trim());
519
        HttpMessage msg = new HttpMessage(url);
520
        //set up properties
521
        Properties arg = new Properties();
522
        arg.put("action", "upload");
523
        arg.put("docid", docid);
524
525
        Properties filenames = new Properties();
526
        filenames.put("datafile", filename);
527
528
        String response = null;
529
        try {
530 2264 sgarg
            response = sendDataForString(arg, filenames, fileData, size);
531 3285 barteau
        } catch (Exception e) {
532 2264 sgarg
            throw new MetacatInaccessibleException(e.getMessage());
533 3285 barteau
        }
534
535
        // Check for an error condition
536
        if (response.indexOf("<error>") != -1) {
537 2264 sgarg
            if (response.indexOf("does not have permission") != -1) {
538 3285 barteau
                throw new InsufficientKarmaException(response);
539 2264 sgarg
            } else {
540 3285 barteau
                throw new MetacatException(response);
541 2264 sgarg
            }
542 3285 barteau
        }
543
544
        return response;
545
    }
546
547 2240 sgarg
    /**
548 1780 jones
     * Delete an XML document in the repository.
549
     *
550
     * @param docid the docid to delete
551 1795 jones
     * @return the metacat response message
552 2240 sgarg
     * @throws InsufficientKarmaException when the user has insufficent rights
553 1780 jones
     *                                    for the operation
554 1795 jones
     * @throws MetacatInaccessibleException when the metacat server can not be
555
     *                                    reached or does not respond
556
     * @throws MetacatException when the metacat server generates another error
557 1780 jones
     */
558 1795 jones
    public String delete(String docid)
559 3285 barteau
    throws InsufficientKarmaException, MetacatException,
560
            MetacatInaccessibleException {
561 1795 jones
        //set up properties
562
        Properties prop = new Properties();
563
        prop.put("action", "delete");
564
        prop.put("docid", docid);
565 3285 barteau
566 1795 jones
        String response = null;
567
        try {
568 2264 sgarg
            response = sendDataForString(prop, null, null, 0);
569 1795 jones
        } catch (Exception e) {
570
            throw new MetacatInaccessibleException(e.getMessage());
571
        }
572 3285 barteau
573 1795 jones
        // Check for an error condition
574
        if (response.indexOf("<error>") != -1) {
575
            if (response.indexOf("does not have permission") != -1) {
576
                throw new InsufficientKarmaException(response);
577
            } else {
578
                throw new MetacatException(response);
579
            }
580
        }
581 2326 harris
        return response;
582
    }
583 3285 barteau
584
585 2326 harris
    /**
586
     * set the access on an XML document in the repository.
587
     *
588 2327 harris
     * @param _docid the docid of the document for which the access should be applied.
589 2326 harris
     *
590
     * @param _principal the document's principal
591
     *
592
     * @param _permission the access permission to be applied to the docid
593
     *  {e.g. read,write,all}
594
     *
595
     * @param _permType the permission type to be applied to the document
596
     *  {e.g. allow or deny}
597
     *
598
     * @param _permOrder the order that the document's permissions should be
599
     *  processed {e.g. denyFirst or allowFirst}
600
     *
601
     *
602
     * @return the metacat response message
603
     *
604
     * @throws InsufficientKarmaException when the user has insufficent rights
605
     *                                    for the operation
606
     * @throws MetacatInaccessibleException when the metacat server can not be
607
     *                                    reached or does not respond
608
     * @throws MetacatException when the metacat server generates another error
609
     */
610
    public String setAccess(String _docid, String _principal, String
611 3285 barteau
            _permission, String _permType,
612
            String _permOrder )
613
            throws InsufficientKarmaException, MetacatException,
614
            MetacatInaccessibleException {
615 2326 harris
        //set up properties
616
        Properties prop = new Properties();
617
        prop.put("action", "setaccess");
618
        prop.put("docid", _docid);
619
        prop.put("principal", _principal);
620
        prop.put("permission", _permission);
621
        prop.put("permType", _permType);
622
        prop.put("permOrder", _permOrder);
623 3285 barteau
624 2326 harris
        String response = null;
625
        try {
626
            response = sendDataForString(prop, null, null, 0);
627
        } catch (Exception e) {
628
            throw new MetacatInaccessibleException(e.getMessage());
629
        }
630 3285 barteau
631 2326 harris
        // Check for an error condition
632
        if (response.indexOf("<error>") != -1) {
633
            if (response.indexOf("does not have permission") != -1) {
634
                throw new InsufficientKarmaException(response);
635
            } else {
636
                throw new MetacatException(response);
637
            }
638
        }
639 1795 jones
        return response;
640 1780 jones
    }
641 3285 barteau
642 1780 jones
    /**
643
     * When the MetacatFactory creates an instance it needs to set the
644
     * MetacatUrl to which connections should be made.
645
     *
646
     * @param metacatUrl the URL for the metacat server
647
     */
648 3285 barteau
    public void setMetacatUrl(String metacatUrl) {
649 1783 jones
        this.metacatUrl = metacatUrl;
650 1780 jones
    }
651 3285 barteau
652 1822 jones
    /**
653
     * Get the session identifier for this session.  This is only valid if
654
     * the login methods has been called successfully for this Metacat object
655
     * beforehand.
656
     *
657
     * @returns the sessionId as a String, or null if the session is invalid
658
     */
659 3285 barteau
    public String getSessionId() {
660 1822 jones
        return this.sessionId;
661
    }
662 3285 barteau
663 1826 jones
    /**
664 2240 sgarg
     * Set the session identifier for this session.  This identifier was
665
     * previously established with a call to login.  To continue to use the
666 1826 jones
     * same session, set the session id before making a call to one of the
667
     * metacat access methods (e.g., read, query, insert, etc.).
668
     *
669
     * @param String the sessionId from a previously established session
670
     */
671 3285 barteau
    public void setSessionId(String sessionId) {
672 1826 jones
        this.sessionId = sessionId;
673
    }
674 2337 tao
675
    /**
676 3285 barteau
     * The method will return the latest revision in metacat server
677 2981 jones
     * for a given document id. If some error happens, this method will throw
678 3285 barteau
     * an exception.
679 2337 tao
     * @param docId String  the given docid you want to use. the docid it self
680
     *                      can have or haven't revision number
681
     * @throws MetacatException
682
     */
683 3285 barteau
    public int getNewestDocRevision(String docId) throws MetacatException {
684
        int rev = 0;
685
        //set up properties
686
        Properties prop = new Properties();
687
        prop.put("action", "getrevisionanddoctype");
688
        prop.put("docid", docId);
689
690
        String response = null;
691
        try {
692
            response = sendDataForString(prop, null, null, 0);
693
            //parseRevisionResponse will return null if there is an
694
            //error that it can't handle
695
            String revStr = parserRevisionResponse(response);
696
            Integer revObj = new Integer(revStr);
697
            rev = revObj.intValue();
698
            // Check for an error condition
699
            if (response.indexOf("<error>") != -1 && revStr == null) {
700
                throw new MetacatException(response);
701
            }
702
        } catch (Exception e) {
703
            throw new MetacatException(e.getMessage());
704
        }
705
        return rev;
706
    }
707
708 2981 jones
    /**
709
     * Return the highest document id for a given scope.  This is used by
710
     * clients to make it easier to determine the next free identifier in a
711 3285 barteau
     * sequence for a given scope.
712 2981 jones
     * @param scope String  the scope to use for looking up the latest id
713
     * @throws MetacatException when an error occurs
714
     */
715
    public String getLastDocid(String scope) throws MetacatException {
716
        String lastIdentifier = "";
717
        //set up properties
718
        Properties prop = new Properties();
719
        prop.put("action", "getlastdocid");
720
        prop.put("scope", scope);
721 3285 barteau
722 2981 jones
        String response = null;
723
        try {
724 2337 tao
            response = sendDataForString(prop, null, null, 0);
725
            // Check for an error condition
726 2981 jones
            if (response.indexOf("<error>") != -1) {
727 3285 barteau
                throw new MetacatException(response);
728 2981 jones
            } else {
729
                Reader responseReader = new StringReader(response);
730 3285 barteau
                Node root =
731
                        XMLUtilities.getXMLReaderAsDOMTreeRootNode(responseReader);
732
                Node docidNode =
733
                        XMLUtilities.getNodeWithXPath(root, "/lastDocid/docid");
734 2986 jones
                lastIdentifier = docidNode.getFirstChild().getNodeValue();
735 2981 jones
            }
736
        } catch (Exception e) {
737 2337 tao
            throw new MetacatException(e.getMessage());
738
        }
739 2981 jones
        return lastIdentifier;
740
    }
741 3141 berkley
742
    /**
743
     * return a list of all docids that match a given scope.  if scope is null
744
     * return all docids registered in the system
745
     * @param scope String  the scope to use to limit the docid query
746
     * @throws MetacatException when an error occurs
747
     */
748
    public Vector getAllDocids(String scope) throws MetacatException {
749
        Vector resultVec = new Vector();
750
        //set up properties
751
        Properties prop = new Properties();
752
        prop.put("action", "getalldocids");
753 3285 barteau
        if(scope != null) {
754
            prop.put("scope", scope);
755 3141 berkley
        }
756 3285 barteau
757 3141 berkley
        String response = null;
758
        try {
759
            response = sendDataForString(prop, null, null, 0);
760
            // Check for an error condition
761
            if (response.indexOf("<error>") != -1) {
762 3285 barteau
                throw new MetacatException(response);
763 3141 berkley
            } else {
764
                Reader responseReader = new StringReader(response);
765 3285 barteau
                Node root =
766
                        XMLUtilities.getXMLReaderAsDOMTreeRootNode(responseReader);
767 3141 berkley
                NodeList nlist = root.getChildNodes();
768 3285 barteau
                for(int i=0; i<nlist.getLength(); i++) {
769
                    Node n = nlist.item(i);
770
                    if(n.getNodeName().equals("docid")) {
771
                        //add the content to the return vector
772
                        String nodeVal = n.getFirstChild().getNodeValue();
773
                        resultVec.addElement(nodeVal);
774
                    }
775 3141 berkley
                }
776
777
            }
778
        } catch (Exception e) {
779
            throw new MetacatException(e.getMessage());
780
        }
781
        return resultVec;
782
    }
783 3143 berkley
784
    /**
785
     * return true of the given docid is registered, false if not
786
     * @param scope String  the scope to use to limit the docid query
787
     * @throws MetacatException when an error occurs
788
     */
789
    public boolean isRegistered(String docid) throws MetacatException {
790
        Vector resultVec = new Vector();
791
        //set up properties
792
        Properties prop = new Properties();
793
        prop.put("action", "isregistered");
794 3285 barteau
        if(docid == null) {
795
            throw new MetacatException("<error>Cannot check if a null docid " +
796
                    "is registered.</error>");
797 3143 berkley
        }
798
        prop.put("docid", docid);
799 3285 barteau
800 3143 berkley
        String response = null;
801
        try {
802
            response = sendDataForString(prop, null, null, 0);
803
            // Check for an error condition
804
            if (response.indexOf("<error>") != -1) {
805 3285 barteau
                throw new MetacatException(response);
806 3143 berkley
            } else {
807
                Reader responseReader = new StringReader(response);
808
                StringBuffer sb = new StringBuffer();
809
                char[] c = new char[1024];
810
                int numread = responseReader.read(c, 0, 1024);
811 3285 barteau
                while(numread != -1) {
812
                    sb.append(new String(c, 0, numread));
813
                    numread = responseReader.read(c, 0, 1024);
814 3143 berkley
                }
815
816
                String responseStr = sb.toString();
817 3285 barteau
                if(responseStr.indexOf("true") != -1) {
818
                    return true;
819 3143 berkley
                }
820
                return false;
821
            }
822
        } catch (Exception e) {
823
            throw new MetacatException(e.getMessage());
824
        }
825
    }
826 3285 barteau
827 3481 barteau
    /**
828
     * Send a request to Metacat.  An alternative to the sentData method.
829
     * Allows for sending multiple parameters with the same name,
830
     * different names, or any combo.  Send properties where the entry
831
     * key contains the "param value",
832
     * and the entry value contains the "param name".
833
     * Constraint: param values must be unique.
834
     *
835
     * @return InputStream as returned by Metacat
836
     * @param args Properties of the parameters to be sent to Metacat, where,
837
     *      key = param value
838
     *      value = param name
839
     * @throws java.lang.Exception thrown
840
     */
841
    synchronized public InputStream sendParameters(Properties args) throws Exception {
842
        InputStream                     result = null;
843
        URL                             url;
844
        HttpMessage                     httpMsg;
845
846
        url = new URL(metacatUrl);
847
        httpMsg = new HttpMessage(url);
848
        httpMsg.setCookie("JSESSIONID="+this.sessionId);
849
        result = httpMsg.sendPostParameters(args);
850
        return(result);
851
    }
852
853 1780 jones
    /************************************************************************
854
     * PRIVATE METHODS
855
     ************************************************************************/
856 3285 barteau
857 1783 jones
    /**
858
     * Send a request to metacat.
859
     *
860
     * @param prop the properties to be URL encoded and sent
861 2264 sgarg
     * @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 1783 jones
     */
868 2240 sgarg
    synchronized private InputStream sendDataOnce(Properties args,
869 3285 barteau
            Properties filename,
870
            InputStream fileData,
871
            int size)
872
            throws Exception {
873 1780 jones
        InputStream returnStream = null;
874
        URL url = new URL(metacatUrl);
875
        HttpMessage msg = new HttpMessage(url);
876 1828 jones
        msg.setCookie("JSESSIONID="+this.sessionId);
877 2264 sgarg
        if (filename == null){
878
            returnStream = msg.sendPostData(args);
879
        } else if (fileData == null){
880
            returnStream = msg.sendPostData(args, filename);
881
        } else if (size > 0) {
882
            returnStream = msg.sendPostData(args, filename, fileData, size);
883 2240 sgarg
        } else {
884 2264 sgarg
            throw new MetacatException("Invalid size specified for " +
885 3285 barteau
                    "the input stream being passed");
886 2240 sgarg
        }
887 1780 jones
        return returnStream;
888
    }
889 3285 barteau
890 1780 jones
    /**
891
     * Send a request to Metacat
892
     *
893 2264 sgarg
     * @param args  the properties to be sent to Metacat
894
     * @param filename  the properties to be sent to Metacat
895
     *                  in case of upload, otherwise null
896
     * @param fileData  the inputStream for the file data to be sent to Metacat
897
     *                  in case of upload, otherwise null
898
     * @param size      the size of the data being sent to Metacat
899
     *                  in case of upload, otherwise 0
900 1780 jones
     * @return      InputStream as returned by Metacat
901
     */
902 3316 barteau
    synchronized public InputStream sendData(Properties args,
903 3285 barteau
            Properties filename,
904
            InputStream fileData,
905
            int size)
906
            throws Exception {
907 1780 jones
        InputStream returnStream = null;
908
        /*
909
            Note:  The reason that there are three try statements all executing
910
            the same code is that there is a problem with the initial connection
911 2240 sgarg
            using the HTTPClient protocol handler.  These try statements make
912
            sure that a connection is made because it gives each connection a
913 1780 jones
            2nd and 3rd chance to work before throwing an error.
914
            THIS IS A TOTAL HACK.  THIS NEEDS TO BE LOOKED INTO AFTER THE BETA1
915
            RELEASE OF MORPHO!!!  cwb (7/24/01)
916 3285 barteau
         */
917 1780 jones
        try {
918 3285 barteau
            return sendDataOnce(args, filename, fileData, size);
919 1780 jones
        } catch (Exception e) {
920
            try {
921 2264 sgarg
                return sendDataOnce(args, filename, fileData, size);
922 1780 jones
            } catch (Exception e2) {
923
                try {
924 2264 sgarg
                    return sendDataOnce(args, filename, fileData, size);
925 1780 jones
                } catch (Exception e3) {
926
                    System.err.println(
927 3196 berkley
                            "Failed to send data to metacat 3 times: " + e3.getMessage());
928
                    System.err.println("metacaturl: " + metacatUrl);
929 1780 jones
                    throw e3;
930
                }
931
            }
932
        }
933
    }
934 3285 barteau
935 1783 jones
    /**
936
     * Send a request to Metacat
937
     *
938 2264 sgarg
     * @param args      the properties to be sent to Metacat
939
     * @param filename  the properties to be sent to Metacat
940
     *                  in case of upload, otherwise null
941
     * @param fileData  the inputStream for the file data to be sent to Metacat
942
     *                  in case of upload, otherwise null
943
     * @param size      the size of the data being sent to Metacat
944
     *                  in case of upload, otherwise 0
945
     * @return          a string as returned by Metacat
946 1783 jones
     */
947 2240 sgarg
    synchronized private String sendDataForString(Properties args,
948 3285 barteau
            Properties filename,
949
            InputStream fileData,
950
            int size)
951
            throws Exception {
952 1783 jones
        String response = null;
953 3285 barteau
954 1783 jones
        try {
955
            InputStreamReader returnStream =
956 2264 sgarg
                    new InputStreamReader(sendData(args, filename,
957 3285 barteau
                    fileData, size));
958 1783 jones
            StringWriter sw = new StringWriter();
959
            int len;
960
            char[] characters = new char[512];
961
            while ((len = returnStream.read(characters, 0, 512)) != -1) {
962
                sw.write(characters, 0, len);
963
            }
964
            returnStream.close();
965
            response = sw.toString();
966
            sw.close();
967
        } catch (Exception e) {
968
            throw e;
969
        }
970
        return response;
971
    }
972 2337 tao
973
    /*
974
     * "getversionanddoctype" action will return a string from metacat server.
975
     * The string format is "revision;doctype"(This is bad idea, we should use xml)
976
     * This method will get revision string from the response string
977
     */
978 3285 barteau
    private String parserRevisionResponse(String response) throws Exception {
979
        String revision = null;
980
        if (response != null) {
981
            if(response.indexOf("<error>") != -1) {
982
                if(response.indexOf("There is not record") != -1) {
983
                    return "0";
984
                } else {
985
                    return null;
986
                }
987
            } else {
988
                int firstSemiCol = response.indexOf(";");
989
                revision = response.substring(0, firstSemiCol);
990
            }
991 2992 berkley
        }
992 3285 barteau
        return revision;
993
    }
994
995
    /**
996
     * JSP API: This is a convenience method to reduce the amount of code in a Metacat Client
997
     * JSP.  It handles creating/reusing an instance of a MetacatClient.
998
     * @param request Since this is intended to be used by a JSP, it is passed the
999
     * available "request" variable (the HttpServletRequest).
1000
     * @throws edu.ucsb.nceas.metacat.client.MetacatInaccessibleException Received by MetacatFactory.
1001
     * @return MetacatClient instance.
1002
     */
1003 3316 barteau
    public static MetacatClient getMetacatClient(HttpServletRequest request) throws MetacatInaccessibleException {
1004 3285 barteau
        MetacatClient                       result;
1005
        String                              metacatPath = "http://%1$s%2$s/metacat";
1006
        String                              host, context;
1007
        javax.servlet.http.HttpSession      session;
1008
1009
        session = request.getSession();
1010
        result = (MetacatClient) session.getAttribute("MetacatClient");
1011
        if (result == null) {
1012
            host = request.getHeader("host");
1013
            context = request.getContextPath();
1014 3362 barteau
            metacatPath = metacatPath.replaceFirst("%1$s", host);
1015
            metacatPath = metacatPath.replaceFirst("%2$s", context);
1016 3285 barteau
            result = (MetacatClient) MetacatFactory.createMetacatConnection(metacatPath);
1017
            session.setAttribute("MetacatClient", result);
1018
        }
1019
        return(result);
1020
    }
1021
1022 1780 jones
}