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