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: Serhan AKIN $'
7
 *     '$Date: 2009-06-13 15:28:13 +0300  $'
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
 */
23
package edu.ucsb.nceas.metacat.dataone;
24

    
25
import java.io.IOException;
26
import java.io.InputStream;
27
import java.io.OutputStream;
28
import java.sql.SQLException;
29
import java.util.Date;
30
import java.util.Enumeration;
31
import java.util.Hashtable;
32
import java.util.Timer;
33

    
34
import javax.servlet.ServletContext;
35
import javax.servlet.http.HttpServletRequest;
36
import javax.servlet.http.HttpServletResponse;
37

    
38
import org.dataone.service.exceptions.IdentifierNotUnique;
39
import org.dataone.service.exceptions.InsufficientResources;
40
import org.dataone.service.exceptions.InvalidRequest;
41
import org.dataone.service.exceptions.InvalidSystemMetadata;
42
import org.dataone.service.exceptions.InvalidToken;
43
import org.dataone.service.exceptions.NotAuthorized;
44
import org.dataone.service.exceptions.NotFound;
45
import org.dataone.service.exceptions.NotImplemented;
46
import org.dataone.service.exceptions.ServiceFailure;
47
import org.dataone.service.exceptions.UnsupportedType;
48
import org.dataone.service.mn.MemberNodeCrud;
49
import org.dataone.service.types.AuthToken;
50
import org.dataone.service.types.Checksum;
51
import org.dataone.service.types.DescribeResponse;
52
import org.dataone.service.types.IdentifierType;
53
import org.dataone.service.types.LogRecordSet;
54
import org.dataone.service.types.SystemMetadata;
55

    
56
import com.gc.iotools.stream.is.InputStreamFromOutputStream;
57

    
58
import edu.ucsb.nceas.metacat.IdentifierManager;
59
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
60
import edu.ucsb.nceas.metacat.McdbException;
61
import edu.ucsb.nceas.metacat.MetacatHandler;
62
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
63
import edu.ucsb.nceas.metacat.service.SessionService;
64
import edu.ucsb.nceas.metacat.util.SessionData;
65
import edu.ucsb.nceas.utilities.ParseLSIDException;
66
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
67

    
68
/**
69
 * 
70
 * Implements DataONE MemberNode CRUD API for Metacat. 
71
 * 
72
 * @author Matthew Jones
73
 */
74
public class CrudService implements MemberNodeCrud {
75

    
76
    private ServletContext servletContext;
77
    private HttpServletRequest request;
78
    private HttpServletResponse response;
79

    
80
//    private Logger logMetacat;
81
    private MetacatHandler handler;
82
//    private String username;
83
//    private String password;
84
//    private String sessionId;
85
//    private String[] groupNames;
86
    private Hashtable<String, String[]> params;
87

    
88
    /**
89
     * Initializes new instance by setting servlet context,request and response.
90
     * TODO: remove dependency on Servlet infrastructure
91
     * TODO: Make this a real service, and make it a Singleton
92
     */
93
    public CrudService(ServletContext servletContext,
94
            HttpServletRequest request, HttpServletResponse response) {
95
        this.servletContext = servletContext;
96
        this.request = request;
97
        this.response = response;
98

    
99
        handler = new MetacatHandler(this.servletContext, new Timer());
100
        initParams();
101
//        loadSessionData();
102
    }
103

    
104
    /**
105
     *  copies request parameters to a Hashtable which is given as argument to 
106
     *  native MetacatHandler functions  
107
     */
108
    private void initParams() {
109

    
110
        String name = null;
111
        String[] value = null;
112
        params = new Hashtable<String, String[]>();
113
        Enumeration paramlist = request.getParameterNames();
114
        while (paramlist.hasMoreElements()) {
115
            name = (String) paramlist.nextElement();
116
            value = request.getParameterValues(name);
117
            params.put(name, value);
118
        }
119
    }
120
    
121
    /**
122
     * 
123
     * Load user details of metacat session from the request 
124
     * 
125
     */
126
//    private void loadSessionData() {
127
//        SessionData sessionData = RequestUtil.getSessionData(request);
128
//
129
//        // TODO: validate the session before allowing these values to be set
130
//        username = sessionData.getUserName();
131
//        password = sessionData.getPassword();
132
//        groupNames = sessionData.getGroupNames();
133
//        sessionId = sessionData.getId();
134
//
135
//        if (username == null) {
136
//            username = "public";
137
//        }
138
//    }
139
    
140
    /*
141
     * Look up the information on the session using the token provided in
142
     * the AuthToken.  The Session should have all relevant user information.
143
     * If the session has expired or is invalid, the 'public' session will
144
     * be returned, giving the user anonymous access.
145
     */
146
    private static SessionData getSessionData(AuthToken token) {
147
        SessionData sessionData = null;
148
        String sessionId = token.getToken();
149
        
150
        // if the session id is registered in SessionService, get the
151
        // SessionData for it. Otherwise, use the public session.
152
        if (SessionService.isSessionRegistered(sessionId)) {
153
            sessionData = SessionService.getRegisteredSession(sessionId);
154
        } else {
155
            sessionData = SessionService.getPublicSession();
156
        }
157
        
158
        return sessionData;
159
    }
160
    
161
    public IdentifierType create(AuthToken token, IdentifierType guid, 
162
            InputStream object, SystemMetadata sysmeta) throws InvalidToken, 
163
            ServiceFailure, NotAuthorized, IdentifierNotUnique, UnsupportedType, 
164
            InsufficientResources, InvalidSystemMetadata, NotImplemented {
165
        throw new NotImplemented(1000, "This method not yet implemented.");
166
    }
167

    
168
    public IdentifierType delete(AuthToken token, IdentifierType guid)
169
            throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
170
            NotImplemented {
171
        throw new NotImplemented(1000, "This method not yet implemented.");
172
    }
173

    
174
    public DescribeResponse describe(AuthToken token, IdentifierType guid)
175
            throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
176
            NotImplemented {
177
        throw new NotImplemented(1000, "This method not yet implemented.");
178
    }
179
    
180
    public InputStream get(AuthToken token, IdentifierType guid)
181
            throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
182
            NotImplemented {
183
        
184
        // Retrieve the session information from the AuthToken
185
        // If the session is expired, then the user is 'public'
186
        final SessionData sessionData = getSessionData(token);
187
        
188
        // Look up the localId for this global identifier
189
        IdentifierManager im = IdentifierManager.getInstance();
190
        try {
191
            final String localId = im.getLocalId(guid.getIdentifier());
192

    
193
            final InputStreamFromOutputStream<String> objectStream = 
194
                new InputStreamFromOutputStream<String>() {
195
                
196
                @Override
197
                public String produce(final OutputStream dataSink) throws Exception {
198

    
199
                    try {
200
                        handler.readFromMetacat(request.getRemoteAddr(), null, 
201
                                dataSink, localId, "xml",
202
                                sessionData.getUserName(), 
203
                                sessionData.getGroupNames(), true, params);
204
                    } catch (PropertyNotFoundException e) {
205
                        throw new ServiceFailure(1030, e.getMessage());
206
                    } catch (ClassNotFoundException e) {
207
                        throw new ServiceFailure(1030, e.getMessage());
208
                    } catch (IOException e) {
209
                        throw new ServiceFailure(1030, e.getMessage());
210
                    } catch (SQLException e) {
211
                        throw new ServiceFailure(1030, e.getMessage());
212
                    } catch (McdbException e) {
213
                        throw new ServiceFailure(1030, e.getMessage());
214
                    } catch (ParseLSIDException e) {
215
                        throw new NotFound(1020, e.getMessage());
216
                    } catch (InsufficientKarmaException e) {
217
                        throw new NotAuthorized(1000, "Not authorized for get().");
218
                    }
219

    
220
                    return "Completed";
221
                }
222
            };
223
            return objectStream;
224

    
225
        } catch (McdbDocNotFoundException e) {
226
            throw new NotFound(1020, e.getMessage());
227
        }
228
        
229
/*    
230
 *      Alternative approach that uses Piped streams, but requires thread handling
231
 *      which makes exception handling difficult (because exceptions fall off the
232
 *      calling thread, terminating the thread.
233
 *      
234
        // Look up the localId for this global identifier
235
        IdentifierManager im = IdentifierManager.getInstance();
236
        try {
237
            final String localId = im.getLocalId(guid.getIdentifier());
238

    
239
            // Now use that localId to read the object and return it
240
            params.put("docid", new String[] { localId });        
241
            final PipedInputStream in = new PipedInputStream();
242
            new Thread(
243
                    new Runnable() {
244
                        public void run() {
245
                            try {
246
                                PipedOutputStream out = new PipedOutputStream(in);
247
                                handler.readFromMetacat(request.getRemoteAddr(), null, 
248
                                        out, localId, "xml",
249
                                        username, groupNames, true, params);
250
                            } catch (PropertyNotFoundException e) {
251
                                throw new ServiceFailure(1030, e.getMessage());
252
                            } catch (ClassNotFoundException e) {
253
                                throw new ServiceFailure(1030, e.getMessage());
254
                            } catch (IOException e) {
255
                                throw new ServiceFailure(1030, e.getMessage());
256
                            } catch (SQLException e) {
257
                                throw new ServiceFailure(1030, e.getMessage());
258
                            } catch (McdbException e) {
259
                                throw new ServiceFailure(1030, e.getMessage());
260
                            } catch (ParseLSIDException e) {
261
                                throw new NotFound(1020, e.getMessage());
262
                            } catch (InsufficientKarmaException e) {
263
                                throw new NotAuthorized(1000, "Not authorized for get().");
264
                            }
265
                        }
266
                    }
267
            ).start();
268
            return in;
269
        } catch (McdbDocNotFoundException e) {
270
            throw new NotFound(1020, e.getMessage());
271
        }        
272
*/
273
    }
274

    
275
    public Checksum getChecksum(AuthToken token, IdentifierType guid)
276
            throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
277
            InvalidRequest, NotImplemented {
278
        throw new NotImplemented(1000, "This method not yet implemented.");
279
    }
280

    
281
    public Checksum getChecksum(AuthToken token, IdentifierType guid, 
282
            String checksumAlgorithm) throws InvalidToken, ServiceFailure, 
283
            NotAuthorized, NotFound, InvalidRequest, NotImplemented {
284
        throw new NotImplemented(1000, "This method not yet implemented.");
285
    }
286

    
287
    public LogRecordSet getLogRecords(AuthToken token, Date fromDate, Date toDate)
288
            throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest, 
289
            NotImplemented {
290
        throw new NotImplemented(1000, "This method not yet implemented.");
291
    }
292

    
293
    public SystemMetadata getSystemMetadata(AuthToken token, IdentifierType guid)
294
            throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
295
            InvalidRequest, NotImplemented {
296
        throw new NotImplemented(1000, "This method not yet implemented.");
297
    }
298

    
299
    public IdentifierType update(AuthToken token, IdentifierType guid, 
300
            InputStream object, IdentifierType obsoletedGuid, SystemMetadata sysmeta) 
301
            throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, 
302
            UnsupportedType, InsufficientResources, NotFound, InvalidSystemMetadata, 
303
            NotImplemented {
304
        throw new NotImplemented(1000, "This method not yet implemented.");
305
    }
306

    
307
}
    (1-1/1)