Project

General

Profile

D1Client.java

refactored to insert possible NotAuthorized situations - Rob Nahf, 2013-08-08 20:39

Download (13.3 KB)

 
1
/**
2
 * This work was created by participants in the DataONE project, and is
3
 * jointly copyrighted by participating institutions in DataONE. For
4
 * more information on DataONE, see our web site at http://dataone.org.
5
 *
6
 *   Copyright ${year}
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *   http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 * 
20
 * $Id$
21
 */
22

    
23
package org.dataone.client;
24

    
25
import java.io.ByteArrayInputStream;
26
import java.io.IOException;
27
import java.util.ArrayList;
28
import java.util.Date;
29
import java.util.List;
30
import java.util.TreeMap;
31

    
32
import org.dataone.client.types.ObsoletesChain;
33
import org.dataone.configuration.Settings;
34
import org.dataone.service.exceptions.IdentifierNotUnique;
35
import org.dataone.service.exceptions.InsufficientResources;
36
import org.dataone.service.exceptions.InvalidRequest;
37
import org.dataone.service.exceptions.InvalidSystemMetadata;
38
import org.dataone.service.exceptions.InvalidToken;
39
import org.dataone.service.exceptions.NotAuthorized;
40
import org.dataone.service.exceptions.NotFound;
41
import org.dataone.service.exceptions.NotImplemented;
42
import org.dataone.service.exceptions.ServiceFailure;
43
import org.dataone.service.exceptions.UnsupportedType;
44
import org.dataone.service.types.v1.Identifier;
45
import org.dataone.service.types.v1.NodeReference;
46
import org.dataone.service.types.v1.Session;
47
import org.dataone.service.types.v1.SystemMetadata;
48

    
49
/**
50
 * The D1Client class represents a client-side implementation of the DataONE
51
 * Service API. The class exposes the DataONE APIs as client methods, dispatches
52
 * the calls to the correct DataONE node, and then returns the results or throws
53
 * the appropriate exceptions.  
54
 */
55
public class D1Client {
56

    
57
    private static CNode cn = null;
58
    
59
        /**
60
         * Get the client instance of the Coordinating Node object for calling Coordinating Node services.
61
         * By default returns the production context CN, defined via the property "D1Client.CN_URL".
62
         * Use of D1Client in other contexts (non-production) requires overriding or changing this 
63
         * property name.  See org.dataone.configuration.Settings class for details.
64
         * 
65
         * @param session - the client session to be used in connections, null uses default behavior. 
66
     * @return the cn
67
         * @throws ServiceFailure 
68
     */
69
    public static CNode getCN(Session session) throws ServiceFailure {
70
        if (cn == null) {
71
                // get the CN URL
72
            String cnUrl = Settings.getConfiguration().getString("D1Client.CN_URL");
73

    
74
                // determine which implementation to instantiate
75
                String cnClassName = Settings.getConfiguration().getString("D1Client.cnClassName");
76
                
77
                if (cnClassName != null) {
78
                        // construct it using reflection
79
                    try {
80
                                        cn = (CNode) Class.forName(cnClassName).newInstance();
81
                                } catch (Exception e) {
82
                                        throw D1Node.recastClientSideExceptionToServiceFailure(e);
83

    
84
                                }
85
                    cn.setNodeBaseServiceUrl(cnUrl);
86
                } else {
87
                        // default
88
                cn = new CNode(cnUrl, session);
89
                }
90
        }
91
        return cn;
92
    }
93
    
94
    
95
    /**
96
         * Get the client instance of the Coordinating Node object for calling Coordinating Node services.
97
         * By default returns the production context CN, defined via the property "D1Client.CN_URL".
98
         * Use of D1Client in other contexts (non-production) requires overriding or changing this 
99
         * property name.  See org.dataone.configuration.Settings class for details.
100
         * 
101
         * Connects using the default session / certificate 
102
     * @return the cn
103
         * @throws ServiceFailure 
104
     */
105
    public static CNode getCN() throws ServiceFailure {
106
        return getCN(null);
107
    }
108
    
109
    
110
    
111
    /**
112
     * Construct and return a Member Node using the base service URL for the node.
113
     * @param mnBaseUrl the service URL for the Member Node
114
     * @return the mn at a particular URL
115
     */
116
    public static MNode getMN(String mnBaseUrl) {
117
        MNode mn = new MNode( mnBaseUrl);
118
        return mn;
119
    }
120
    
121
    
122
    /**
123
     * Construct and return a Member Node using the nodeReference
124
     * for the member node.  D1Client's cn instance will look up the
125
     * member node's baseURL from the passed in nodeReference
126
     * 
127
     * @param nodeRef
128
     * @return
129
     * @throws ServiceFailure
130
     */
131
    public static MNode getMN(NodeReference nodeRef) throws ServiceFailure {
132
            CNode cn;
133
                try {
134
                        cn = getCN();
135
                } catch (Exception e) {
136
                        throw D1Node.recastClientSideExceptionToServiceFailure(e);
137
                }
138
            String mnBaseUrl = null;
139
                try {
140
                        mnBaseUrl = cn.lookupNodeBaseUrl(nodeRef.getValue());
141
                        if (mnBaseUrl == null) 
142
                                throw new ServiceFailure("0000","Failed to find baseUrl for node " + nodeRef.getValue() + " in the NodeList");
143
                } catch (NotImplemented e) {
144
                        throw D1Node.recastClientSideExceptionToServiceFailure(e);
145
                }
146
        MNode mn = new MNode(mnBaseUrl);
147
        return mn;
148
    }
149
    
150
    
151
    /**
152
     * Attempts to create the given D1Object on the originMemberNode contained 
153
     * in its SystemMetadata.  Does not perform any identifier reservation checks
154
     * or make any reservations.
155
     * 
156
     * @param session
157
     * @param d1object - the d1object representing both the data bytes and systemMetadata
158
     * @return the Identifier returned from the mn.create call
159
     * 
160
     * @throws InvalidToken
161
     * @throws ServiceFailure
162
     * @throws NotAuthorized
163
     * @throws IdentifierNotUnique
164
     * @throws UnsupportedType
165
     * @throws InsufficientResources
166
     * @throws InvalidSystemMetadata
167
     * @throws NotImplemented
168
     * @throws InvalidRequest
169
     */
170
    public static Identifier create(Session session, D1Object d1object) throws InvalidToken, ServiceFailure, NotAuthorized, 
171
    IdentifierNotUnique, UnsupportedType, InsufficientResources, InvalidSystemMetadata, NotImplemented, InvalidRequest 
172
    {
173
            SystemMetadata sysmeta = d1object.getSystemMetadata();
174
            if (sysmeta == null) 
175
                    throw new InvalidRequest("Client Error", "systemMetadata of the D1Object cannot be null");
176

    
177
            String mn_url = D1Client.getCN().lookupNodeBaseUrl(sysmeta.getOriginMemberNode().getValue());
178
            MNode mn = D1Client.getMN(mn_url);
179
            Identifier rGuid;
180
                try {
181
                        rGuid = mn.create(session, sysmeta.getIdentifier(), 
182
                                        d1object.getDataSource().getInputStream(), sysmeta);
183
                } catch (IOException e) {
184
                        throw new ServiceFailure("000 Client Exception","Could not open InputStream from the data: " + e.getMessage());
185
                }
186
            return rGuid;
187
    }
188
    
189
    
190
    /**
191
     * Perform an update an object in DataONE with the given D1Object on the 
192
     * originMemberNode contained in its systemMetadata. 
193
     * 
194
     * For this operation to work, the D1Object's systemMetadata needs have the
195
     * obsoletes field set with the object to be updated, and the originMemberNode
196
     * needs to match the authoritativeMemberNode of the object being updated.
197
     * 
198
     * As with D1Client.create(), this method does not perform any identifier
199
     * reservation checks or make any reservations.
200
     * 
201
     * @param session
202
     * @param d1object - the d1object representing both the data bytes and systemMetadata
203
     * @return the Identifier returned from the mn.create call
204
     * 
205
     * @throws InvalidToken
206
     * @throws ServiceFailure
207
     * @throws NotAuthorized
208
     * @throws IdentifierNotUnique
209
     * @throws UnsupportedType
210
     * @throws InsufficientResources
211
     * @throws InvalidSystemMetadata
212
     * @throws NotImplemented
213
     * @throws InvalidRequest
214
     * @throws NotFound 
215
     * @since v1.2
216
     */
217
    public static Identifier update(Session session, D1Object d1object) 
218
    throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, 
219
    UnsupportedType, InsufficientResources, InvalidSystemMetadata, NotImplemented, 
220
    InvalidRequest, NotFound 
221
    {
222
            SystemMetadata sysmeta = d1object.getSystemMetadata();
223
            if (sysmeta == null) 
224
                    throw new InvalidRequest("Client Error", "systemMetadata of the D1Object cannot be null");
225

    
226
            String mn_url = D1Client.getCN().lookupNodeBaseUrl(sysmeta.getOriginMemberNode().getValue());
227
            MNode mn = D1Client.getMN(mn_url);
228
            Identifier rGuid;
229
                try {
230
                        rGuid = mn.update(sysmeta.getObsoletes(), d1object.getDataSource().getInputStream(), 
231
                                        sysmeta.getIdentifier(),sysmeta);
232
                } catch (IOException e) {
233
                        throw new ServiceFailure("000 Client Exception","Could not open InputStream from the data: " + e.getMessage());
234
                }
235
            return rGuid;
236
    }
237
    
238
    
239
    
240
    /**
241
     * Perform an archive on an object in DataONE with the given D1Object on the 
242
     * authoritativeMemberNode contained in its systemMetadata. 
243
     * 
244
     * @param session
245
     * @param d1object - the d1object representing both the data bytes and systemMetadata
246
     * @return the Identifier returned from the mn.archive call
247
     * 
248
     * @throws InvalidToken
249
     * @throws ServiceFailure
250
     * @throws NotAuthorized
251
     * @throws NotImplemented
252
     * @throws InvalidRequest
253
     * @throws NotFound
254
     * @since v1.2 
255
     */
256
    public static Identifier archive(Session session, D1Object d1object) 
257
    throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest 
258
    {
259
            SystemMetadata sysmeta = d1object.getSystemMetadata();
260
            if (sysmeta == null) 
261
                    throw new InvalidRequest("Client Error", "systemMetadata of the D1Object cannot be null");
262

    
263
            String mn_url = D1Client.getCN().lookupNodeBaseUrl(sysmeta.getAuthoritativeMemberNode().getValue());
264
            MNode mn = D1Client.getMN(mn_url);
265
            Identifier rGuid;
266
                rGuid = mn.archive(d1object.getIdentifier());
267
            return rGuid;
268
    }
269

    
270
    
271
    /**
272
     * Attempts to create the DataPackage.  First makes sure there is a D1Object
273
     * representing the ORE resource map, then delegates D1Object creation to 
274
     * D1Client.create(D1Object),
275
     * 
276
     * @since Not Implemented - need to determine correct assumptions and behavior
277
     * 
278
     * @param session
279
     * @param dataPackage
280
     * @return
281
     * @throws NotImplemented 
282
     */
283
    
284
    /* TODO: determine how to identify which objects are already created
285
     * TODO: determine behavior under situations where exceptions thrown half-way 
286
     * through.  Cannot package into a transaction.  
287
     * data objects and science metadata objects that don't already exist on a MN and then
288
     * create the ORE resource map on the MN
289
     */   
290
//    public static Identifier create(Session session, DataPackage dataPackage) throws NotImplemented {
291
//            throw new NotImplemented("Client Exception", "this method has not been implemented yet.");
292
//    }
293
    
294
    
295
    /**
296
     * Return the full ObsoletesChain for the given Identifier.  Includes 
297
     * predecessors and antecedents. 
298
     * @param pid
299
     * @return a complete ObsoletesChain
300
     * @throws InvalidToken
301
     * @throws ServiceFailure
302
     * @throws NotAuthorized
303
     * @throws NotFound
304
     * @throws NotImplemented
305
     * @since v1.2
306
     */
307
    public static ObsoletesChain listUpdateHistory(Identifier pid) 
308
    throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented 
309
    {
310
            Identifier startingPid = pid;
311
            ObsoletesChain chain = new ObsoletesChain(startingPid);
312

    
313
            SystemMetadata smd = null;
314
            try {
315
                    try {
316
                            smd = getCN().getSystemMetadata(startingPid, true);
317
                            chain.addObject(
318
                                            pid, 
319
                                            smd.getDateUploaded(), 
320
                                            smd.getObsoletes(), 
321
                                            smd.getObsoletedBy(), 
322
                                            smd.getArchived(),
323
                                            false);
324
                    }
325
                    catch (NotAuthorized na) {
326
                            chain.addObject(
327
                                            startingPid, 
328
                                            null, 
329
                                            null,
330
                                            null,
331
                                            null,
332
                                            true);
333
                    }
334

    
335
                    Identifier fpid = smd.getObsoletedBy();
336
                    Identifier bpid = smd.getObsoletes();
337
                
338
                    try {
339
                            while (fpid != null) {
340
                                    smd = getCN().getSystemMetadata(fpid, true);
341
                                    chain.addObject(
342
                                                    fpid, 
343
                                                    smd.getDateUploaded(), 
344
                                                    smd.getObsoletes(), 
345
                                                    smd.getObsoletedBy(), 
346
                                                    smd.getArchived(),
347
                                                    false);
348
                                    fpid = smd.getObsoletedBy();
349
                            }
350
                    } catch (NotAuthorized e) {
351
                            chain.addObject(
352
                                                fpid, 
353
                                                null, 
354
                                                null,
355
                                                null,
356
                                                null,
357
                                                true);
358
                    }
359
            
360
                    // get the first obsoletes by looking up in the stored list
361
                    try {
362
                            while (bpid != null) {
363
                                    smd = getCN().getSystemMetadata(bpid, true);
364
                                    chain.addObject(
365
                                                    bpid, 
366
                                                    smd.getDateUploaded(), 
367
                                                    smd.getObsoletes(), 
368
                                                    smd.getObsoletedBy(), 
369
                                                    smd.getArchived(),
370
                                                    false);
371
                                    bpid = smd.getObsoletes();
372
                            }
373
                    } catch (NotAuthorized e) {
374
                            chain.addObject(
375
                                            bpid, 
376
                                            null, 
377
                                            null,
378
                                            null,
379
                                            null,
380
                                            true);
381
                    }
382
            } catch (NullPointerException npe) {
383
                    ServiceFailure sf = new ServiceFailure("0000", 
384
                                    "Likely Null value for required systemMetadata field for: " + 
385
                                    smd.getIdentifier() + npe.getMessage());
386
                    sf.setStackTrace(npe.getStackTrace());
387
                    throw sf;
388
            }
389
            return chain;
390
    }
391
}
Add picture from clipboard (Maximum size: 14.8 MB)