Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2000 Regents of the University of California and the
4
 *              National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author: tao $'
7
 *     '$Date: 2003-09-04 17:57:22 -0700 (Thu, 04 Sep 2003) $'
8
 * '$Revision: 1818 $'
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.stringclient.impl;
26

    
27
import java.io.BufferedReader;
28
import java.io.InputStream;
29
import java.io.InputStreamReader;
30
import java.io.PushbackReader;
31
import java.io.IOException;
32
import java.io.StringWriter;
33
import java.io.Reader;
34
import java.net.URL;
35
import java.util.Properties;
36

    
37
import edu.ucsb.nceas.utilities.HttpMessage;
38

    
39

    
40
import org.globus.ogsa.impl.ogsi.GridServiceImpl;
41
import edu.ucsb.nceas.metacat.stringclient.MetacatString.MetacatStringPortType;
42
import java.rmi.RemoteException;
43

    
44
/**
45
 *  This interface provides methods for initializing and logging in to a 
46
 *  Metacat server, and then querying, reading, transforming, inserting, 
47
 *  updating and deleting documents from that server.
48
 */
49
public class MetacatStringImpl extends GridServiceImpl 
50
                               implements MetacatStringPortType
51
{
52
    /** The URL string for the metacat server */
53
    private String metacatUrl="http://dev.nceas.ucsb.edu/tao/servlet/metacat";
54

    
55
    /**
56
     *  Method used to log in to a metacat server. Implementations will need
57
     *  to cache a cookie value to make the session persistent.  Each time a
58
     *  call is made to one of the other methods (e.g., read), the cookie will
59
     *  need to be passed back to the metacat server along with the request.
60
     *
61
     *  @param username   the username of the user, like an LDAP DN
62
     *  @param password   the password for that user for authentication
63
     */
64
    public void login(String username, String password) throws RemoteException
65
        
66
    {
67
        Properties prop = new Properties();
68
        prop.put("action", "login");
69
        prop.put("qformat", "xml");
70
        prop.put("username", username);
71
        prop.put("password", password);
72

    
73
        String response = null;
74
        try {
75
            response = sendDataForString(prop);
76
        } catch (Exception e) {
77
            throw new RemoteException(e.getMessage());
78
        }
79

    
80
        if (response.indexOf("<login>") == -1) {
81
            HttpMessage.setCookie(null);
82
            throw new RemoteException(response);
83
        }
84
    }
85

    
86
    /**
87
     *  Method used to log out a metacat server. When Metacat server will end
88
     *  the session when this call is invoken.
89
     *
90
     *  @throws MetacatInaccessibleException when the metacat server can not be
91
     *                                    reached or does not respond
92
     */
93
    public void logout() throws RemoteException
94
    {
95
        Properties prop = new Properties();
96
        prop.put("action", "logout");
97
        prop.put("qformat", "xml"); 
98
       
99
        String response = null;
100
        try {
101
            response = sendDataForString(prop);
102
        } catch (Exception e) {
103
            throw new RemoteException(e.getMessage());
104
        }
105
        
106
        if (response.indexOf("<logout>") == -1) {
107
            throw new RemoteException(response);
108
        }
109
    }
110
    
111
    
112
    /**
113
     * Read an XML document from the metacat server session, accessed by docid,
114
     * and returned as a String.
115
     *
116
     * @param docid the identifier of the document to be read
117
     * @return a String for accessing the document
118
     */
119
    public String read(String docid) throws RemoteException
120
    {
121
        Properties prop = new Properties();
122
        prop.put("action", "read");
123
        prop.put("qformat", "xml");
124
        prop.put("docid", docid);
125

    
126
        String response = null;
127
        try {
128
            response = sendDataForString(prop);
129
        } catch (Exception e) {
130
            throw new RemoteException(e.getMessage());
131
        }
132
        if (response != null && response.indexOf("<error>") != -1) {
133
                if (response.indexOf("does not have permission") != -1) {
134
                    throw new RemoteException(response);
135
                } else {
136
                    throw new RemoteException(response);
137
                }
138
         }
139
     
140
        return response;
141
    }
142

    
143
    /**
144
     * Query the metacat document store with the given metacat-compatible 
145
     * query document, and return the result set as a Reader.
146
     *
147
     * @param xmlQuery a string for accessing the XML version of the query
148
     * @return a string for accessing the result set
149
     */
150
    public String query(String xmlQuery) throws RemoteException 
151
    {
152
        String query = xmlQuery;
153
      
154
        //set up properties
155
        Properties prop = new Properties();
156
        prop.put("action", "squery");
157
        prop.put("qformat", "xml");
158
        prop.put("query", query);
159
        
160
        String response = null;
161
        try {
162
            response = sendDataForString(prop);
163
          
164
        } catch (Exception e) {
165
            throw new RemoteException(e.getMessage());
166
        }
167
       
168
        return response;
169
    }
170

    
171
    /**
172
     * Insert an XML document into the repository.
173
     *
174
     * @param docid the docid to insert the document
175
     * @param xmlDocument a Reader for accessing the XML document to be inserted
176
     * @param schema a Reader for accessing the DTD or XML Schema for 
177
     *               the document
178
     * @return the metacat response message
179
     */
180
    public String insert(String docid, String xmlDocument, String schema)
181
        throws RemoteException
182
    {
183
        String doctext = xmlDocument;
184
        String schematext = schema;
185
     
186
     //set up properties
187
        Properties prop = new Properties();
188
        prop.put("action", "insert");
189
        prop.put("docid", docid);
190
        prop.put("doctext", doctext);
191
        if (schematext != null) {
192
            prop.put("dtdtext", schematext);
193
        }
194
        
195
        String response = null;
196
        try {
197
            response = sendDataForString(prop);
198
        } catch (Exception e) {
199
            throw new RemoteException(e.getMessage());
200
        }
201

    
202
        // Check for an error condition
203
        if (response.indexOf("<error>") != -1) {
204
            if (response.indexOf("does not have permission") != -1) {
205
                throw new RemoteException(response);
206
            } else {
207
                throw new RemoteException(response);
208
            }
209
        }
210

    
211
        return response;
212
    }
213

    
214
    /**
215
     * Update an XML document in the repository.
216
     *
217
     * @param docid the docid to update
218
     * @param xmlDocument a Reader for accessing the XML text to be updated
219
     * @param schema a Reader for accessing the DTD or XML Schema for 
220
     *               the document
221
     * @return the metacat response message
222
     */
223
    public String update(String docid, String xmlDocument, String schema)
224
        throws RemoteException
225
    {
226
        String doctext = xmlDocument;
227
        String schematext = schema;
228
      
229

    
230
        //set up properties
231
        Properties prop = new Properties();
232
        prop.put("action", "update");
233
        prop.put("docid", docid);
234
        prop.put("doctext", doctext);
235
        if (schematext != null) {
236
            prop.put("dtdtext", schematext);
237
        }
238
        
239
        String response = null;
240
        try {
241
            response = sendDataForString(prop);
242
        } catch (Exception e) {
243
            throw new RemoteException(e.getMessage());
244
        }
245

    
246
        // Check for an error condition
247
        if (response.indexOf("<error>") != -1) {
248
            if (response.indexOf("does not have permission") != -1) {
249
                throw new RemoteException(response);
250
            } else {
251
                throw new RemoteException(response);
252
            }
253
        }
254

    
255
        return response;
256
    }
257

    
258
    /**
259
     * Delete an XML document in the repository.
260
     *
261
     * @param docid the docid to delete
262
     * @return the metacat response message
263
     */
264
    public String delete(String docid) throws RemoteException
265
    {
266
        //set up properties
267
        Properties prop = new Properties();
268
        prop.put("action", "delete");
269
        prop.put("docid", docid);
270
        
271
        String response = null;
272
        try {
273
            response = sendDataForString(prop);
274
        } catch (Exception e) {
275
            throw new RemoteException(e.getMessage());
276
        }
277

    
278
        // Check for an error condition
279
        if (response.indexOf("<error>") != -1) {
280
            if (response.indexOf("does not have permission") != -1) {
281
                throw new RemoteException(response);
282
            } else {
283
                throw new RemoteException(response);
284
            }
285
        }
286

    
287
        return response;
288
    }
289
    
290
    /**
291
     * When the MetacatFactory creates an instance it needs to set the
292
     * MetacatUrl to which connections should be made.
293
     *
294
     * @param metacatUrl the URL for the metacat server
295
     */
296
    public void setMetacatUrl(String metacatUrl) throws RemoteException
297
    {
298
      this.metacatUrl = metacatUrl;
299
    }
300
 
301
    /************************************************************************
302
     * PRIVATE METHODS
303
     ************************************************************************/
304

    
305
    /**
306
     * Send a request to metacat.
307
     *
308
     * @param prop the properties to be URL encoded and sent
309
     */
310
    synchronized private InputStream sendDataOnce(Properties prop) 
311
        throws Exception
312
    {
313
        InputStream returnStream = null;
314
        URL url = new URL(metacatUrl);
315
        HttpMessage msg = new HttpMessage(url);
316
        returnStream = msg.sendPostData(prop);
317
        return returnStream;
318
    }
319

    
320
    /**
321
     * Send a request to Metacat
322
     *
323
     * @param prop  the properties to be sent to Metacat
324
     * @return      InputStream as returned by Metacat
325
     */
326
    synchronized private InputStream sendData(Properties prop) throws Exception
327
    {   
328
        InputStream returnStream = null;
329

    
330
        /*
331
            Note:  The reason that there are three try statements all executing
332
            the same code is that there is a problem with the initial connection
333
            using the HTTPClient protocol handler.  These try statements make 
334
            sure that a connection is made because it gives each connection a 
335
            2nd and 3rd chance to work before throwing an error.
336
            THIS IS A TOTAL HACK.  THIS NEEDS TO BE LOOKED INTO AFTER THE BETA1
337
            RELEASE OF MORPHO!!!  cwb (7/24/01)
338
          */
339
        try {
340
           return sendDataOnce(prop);
341
        } catch (Exception e) {
342
            try {
343
                return sendDataOnce(prop);
344
            } catch (Exception e2) {
345
                try {
346
                    return sendDataOnce(prop);
347
                } catch (Exception e3) {
348
                    System.err.println(
349
                            "Failed to send data to metacat 3 times.");
350
                    throw e3;
351
                }
352
            }
353
        }
354
    }
355

    
356
    /**
357
     * Send a request to Metacat
358
     *
359
     * @param prop  the properties to be sent to Metacat
360
     * @return      a string as returned by Metacat
361
     */
362
    synchronized private String sendDataForString(Properties prop) 
363
        throws Exception
364
    {
365
        String response = null;
366

    
367
        try {
368
            InputStreamReader returnStream =
369
                    new InputStreamReader(sendData(prop));
370
            StringWriter sw = new StringWriter();
371
            int len;
372
            char[] characters = new char[512];
373
            while ((len = returnStream.read(characters, 0, 512)) != -1) {
374
                sw.write(characters, 0, len);
375
            }
376
            returnStream.close();
377
            response = sw.toString();
378
            sw.close();
379
        } catch (Exception e) {
380
            throw e;
381
        }
382
        return response;
383
    }
384
}
(2-2/2)