Project

General

Profile

« Previous | Next » 

Revision 8452

(task #6297): sync pid(s) access policy between member node and coordinating node

View differences:

src/edu/ucsb/nceas/metacat/dataone/SyncAccessPolicy.java
1
package edu.ucsb.nceas.metacat.dataone;
2

  
3
/**
4
 *  '$RCSfile$'
5
 *    Purpose: A Class for upgrading the database to version 1.5
6
 *  Copyright: 2000 Regents of the University of California and the
7
 *             National Center for Ecological Analysis and Synthesis
8
 *    Authors: Peter Slaughter
9
 *
10
 *   '$Author: slaughter $'
11
 *     '$Date:$'
12
 * '$Revision:$'
13
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 2 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27
 */
28

  
29
import java.math.BigInteger;
30
import java.sql.SQLException;
31
import java.util.ArrayList;
32
import java.util.Arrays;
33
import java.util.Date;
34
import java.util.HashMap;
35
import java.util.HashSet;
36
import java.util.List;
37
import java.util.Map;
38
import java.util.Set;
39

  
40
import org.apache.log4j.Logger;
41
import org.dataone.client.CNode;
42
import org.dataone.client.D1Client;
43
import org.dataone.service.exceptions.InvalidRequest;
44
import org.dataone.service.exceptions.InvalidToken;
45
import org.dataone.service.exceptions.NotAuthorized;
46
import org.dataone.service.exceptions.NotFound;
47
import org.dataone.service.exceptions.NotImplemented;
48
import org.dataone.service.exceptions.ServiceFailure;
49
import org.dataone.service.exceptions.VersionMismatch;
50
import org.dataone.service.types.v1.AccessPolicy;
51
import org.dataone.service.types.v1.Identifier;
52
import org.dataone.service.types.v1.ObjectFormatIdentifier;
53
import org.dataone.service.types.v1.ObjectInfo;
54
import org.dataone.service.types.v1.ObjectList;
55
import org.dataone.service.types.v1.Permission;
56
import org.dataone.service.types.v1.Session;
57
import org.dataone.service.types.v1.Subject;
58
import org.dataone.service.types.v1.SystemMetadata;
59

  
60
import edu.ucsb.nceas.metacat.AccessionNumberException;
61
import edu.ucsb.nceas.metacat.IdentifierManager;
62
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
63
import edu.ucsb.nceas.metacat.properties.PropertyService;
64
import edu.ucsb.nceas.metacat.shared.ServiceException;
65
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
66
import edu.ucsb.nceas.utilities.SortedProperties;
67

  
68
public class SyncAccessPolicy {
69

  
70
	private static Logger logMetacat = Logger.getLogger(SyncAccessPolicy.class);
71

  
72
	/**
73
	 * Synchronize access policy (from system metadata) of d1 member node with
74
	 * the corresponding controlling node.
75
	 * 
76
	 * @param objList
77
	 *            list of d1 objects to be synced
78
	 * @return syncedIds a list of pids that were synced with the CN
79
	 * @throws ServiceFailure
80
	 * @throws InvalidToken
81
	 * @throws NotAuthorized
82
	 * @throws NotFound
83
	 * @throws NotImplemented
84
	 * @throws McdbDocNotFoundException
85
	 * @throws InvalidRequest
86
	 * @throws VersionMismatch
87
	 * @throws SQLException
88
	 * @throws AccessionNumberException
89
	 * @throws NumberFormatException
90
	 */
91
	public List<Identifier> sync(ObjectList objList) throws ServiceFailure,
92
			InvalidToken, NotAuthorized, NotFound, NotImplemented,
93
			McdbDocNotFoundException, InvalidRequest, VersionMismatch,
94
			NumberFormatException, AccessionNumberException, SQLException {
95

  
96
		AccessPolicy cnAccessPolicy = null;
97
		String guid = null;
98
		AccessPolicy mnAccessPolicy = null;
99
		Identifier pid = null;
100
		ObjectInfo objInfo = null;
101
		pid = new Identifier();
102
		Session session = null;
103
		List<Identifier> syncedIds = new ArrayList<Identifier>();
104
		SystemMetadata cnSysMeta = null;
105
		SystemMetadata mnSysMeta = null;
106

  
107
		CNode cn = D1Client.getCN();
108

  
109
		for (int i = objList.getStart(); i <= objList.getCount(); i++) {
110

  
111
			objInfo = objList.getObjectInfo(i);
112
			pid = objInfo.getIdentifier();
113
			try {
114
				// Get sm, access policy for requested localId
115
				mnSysMeta = IdentifierManager.getInstance().getSystemMetadata(
116
						pid.getValue());
117

  
118
			} catch (McdbDocNotFoundException e) {
119
				logMetacat.error("Error syncing access policy of pid: "
120
						+ pid.getValue() + " pid not found: " + e.getMessage());
121
			} catch (Exception e) {
122
				logMetacat.error("Error syncing access policy of pid: "
123
						+ pid.getValue() + e.getMessage());
124
			}
125

  
126
			mnAccessPolicy = mnSysMeta.getAccessPolicy();
127
			// System.out.println("pid: " +
128
			// mnSysMeta.getIdentifier().toString());
129

  
130
			// Get sm, access policy for requested pid from the CN
131
			// BigInteger mnSerialVersion = mnSysMeta.getSerialVersion();
132

  
133
			try {
134
				cnSysMeta = cn.getSystemMetadata(pid);
135
			} catch (Exception e) {
136
				logMetacat.error("Error getting system metadata for pid: "
137
						+ pid.getValue() + " from cn: " + e.getMessage());
138
			}
139
			
140
			cnAccessPolicy = cnSysMeta.getAccessPolicy();
141

  
142
			// Compare access policy of MN and CN, and update if different
143
			if (!isEqual(mnAccessPolicy, cnAccessPolicy)) {
144
				try {
145
					BigInteger serialVersion = cnSysMeta.getSerialVersion();
146
					cn.setAccessPolicy(session, pid,
147
							mnSysMeta.getAccessPolicy(),
148
							serialVersion.longValue());
149
					// Add this pid to the list of pids that were successfully synced
150
					syncedIds.add(pid);
151
				} catch (Exception e) {
152
					logMetacat.error("Error setting access policy of pid: "
153
							+ pid.getValue() + " with cn: " + e.getMessage());
154
				}
155

  
156
			}
157
		}
158

  
159
		return syncedIds;
160
	}
161

  
162
	/**
163
	 * Convenience function that accepts a list of guids to sync
164
	 * 
165
	 * @param guidsToSync
166
	 *            list of guids to have access policy synced for
167
	 * @return syncedPids - list of pids that were actually synced with the CN
168
	 * @throws NumberFormatException
169
	 * @throws ServiceFailure
170
	 * @throws InvalidToken
171
	 * @throws NotAuthorized
172
	 * @throws NotFound
173
	 * @throws NotImplemented
174
	 * @throws McdbDocNotFoundException
175
	 * @throws InvalidRequest
176
	 * @throws VersionMismatch
177
	 * @throws AccessionNumberException
178
	 * @throws SQLException
179
	 */
180
	public List<Identifier> sync(List<String> guidsToSync)
181
			throws NumberFormatException, ServiceFailure, InvalidToken,
182
			NotAuthorized, NotFound, NotImplemented, McdbDocNotFoundException,
183
			InvalidRequest, VersionMismatch, AccessionNumberException,
184
			SQLException {
185
		List<Identifier> syncedPids = null;
186
		ObjectList objList = new ObjectList();
187
		SystemMetadata sm = new SystemMetadata();
188

  
189
		int start = 0;
190
		int count = guidsToSync.size();
191
		int total = count;
192

  
193
		objList.setStart(start);
194
		objList.setCount(count);
195
		objList.setTotal(total);
196

  
197
		// Convert the guids to d1 objects, as this is what
198
		// IdentifierManager.getInstance().querySystemMetadata returns in
199
		// syncAll, and
200
		// what sync(ObjectList...) expects
201
		for (String guid : guidsToSync) {
202

  
203
			try {
204
				sm = IdentifierManager.getInstance().getSystemMetadata(guid);
205
			} catch (Exception e) {
206
				logMetacat.error("Error syncing access policy of pid: " + guid
207
						+ e.getMessage());
208
			}
209

  
210
			logMetacat.debug("Got sm for guid: " + guid);
211
			ObjectInfo oi = new ObjectInfo();
212

  
213
			Identifier id = new Identifier();
214
			id.setValue(guid);
215
			oi.setIdentifier(id);
216

  
217
			oi.setDateSysMetadataModified(sm.getDateSysMetadataModified());
218

  
219
			oi.setChecksum(sm.getChecksum());
220
			oi.setFormatId(sm.getFormatId());
221
			oi.setSize(sm.getSize());
222
			objList.addObjectInfo(oi);
223
		}
224

  
225
		syncedPids = sync(objList);
226
		return syncedPids;
227
	}
228

  
229
	public List<Identifier> syncAll() throws ServiceFailure, InvalidToken,
230
			NotAuthorized, NotFound, NotImplemented, McdbDocNotFoundException,
231
			InvalidRequest, VersionMismatch, NumberFormatException,
232
			AccessionNumberException, SQLException, PropertyNotFoundException,
233
			ServiceException {
234

  
235
		// For the following query parameters - null indicates that the query
236
		// will not be
237
		// constrained by the parameter.
238
		Date startTime = null;
239
		Date endTime = null;
240
		ObjectFormatIdentifier objectFormatId = null;
241
		Boolean replicaStatus = false; // return only pids for which this mn is
242
										// authoritative
243
		Integer start = null;
244
		Integer count = null;
245

  
246
		ObjectList objsToSync = IdentifierManager.getInstance()
247
				.querySystemMetadata(startTime, endTime, objectFormatId,
248
						replicaStatus, start, count);
249

  
250
		List<Identifier> syncedIds = sync(objsToSync);
251

  
252
		return syncedIds;
253
	}
254

  
255
	/**
256
	 * Compare two d1 system metadata access policies for equivalence.
257
	 * 
258
	 * @param ap1
259
	 *            - first access policy in the comparison
260
	 * @param ap2
261
	 *            - second access policy in the comparison
262
	 * @return
263
	 */
264
	private boolean isEqual(AccessPolicy ap1, AccessPolicy ap2) {
265

  
266
		// Get the list of access rules for each access policy
267
		List<org.dataone.service.types.v1.AccessRule> allowList1 = ap1
268
				.getAllowList();
269
		List<org.dataone.service.types.v1.AccessRule> allowList2 = ap2
270
				.getAllowList();
271

  
272
		HashMap<Subject, Set<Permission>> userPerms1 = new HashMap<Subject, Set<Permission>>();
273
		HashMap<Subject, Set<Permission>> userPerms2 = new HashMap<Subject, Set<Permission>>();
274

  
275
		// Load the permissions from the access rules into a hash of sets, i.e.,
276
		// so that we end up with this:
277
		// hash key: set of permissions
278
		// ----------------------------
279
		// user1: read, write
280
		// user2: read
281
		// user3: read, write, change permissions
282
		// With the permissions in this structure, they can be easily compared
283
		Set<Permission> perms = null;
284
		// Process first access policy
285
		for (org.dataone.service.types.v1.AccessRule accessRule : allowList1) {
286
			for (Subject s : accessRule.getSubjectList()) {
287
				if (userPerms1.containsKey(s)) {
288
					perms = userPerms1.get(s);
289
				} else {
290
					perms = new HashSet<Permission>();
291
				}
292
				for (Permission p : accessRule.getPermissionList()) {
293
					perms.add(p);
294
				}
295
			}
296
		}
297

  
298
		// Process second access policy
299
		for (org.dataone.service.types.v1.AccessRule accessRule : allowList2) {
300
			for (Subject s : accessRule.getSubjectList()) {
301
				if (userPerms2.containsKey(s)) {
302
					perms = userPerms2.get(s);
303
				} else {
304
					perms = new HashSet<Permission>();
305
				}
306
				for (Permission p : accessRule.getPermissionList()) {
307
					perms.add(p);
308
				}
309
			}
310
		}
311

  
312
		// Now perform the comparison. This test assumes that the mn perms are
313
		// more
314
		// complete than the cn perms.
315
		for (Map.Entry<Subject, Set<Permission>> entry : userPerms1.entrySet()) {
316
			// User name
317
			Subject s1 = entry.getKey();
318
			// Perms that the user holds
319
			Set p1 = entry.getValue();
320

  
321
			// Does this user in both access policies?
322
			if (userPerms2.containsKey(s1)) {
323
				if (!p1.equals(userPerms2.get(p1))) {
324
					return false;
325
				}
326
			} else {
327
				return false;
328
			}
329
		}
330

  
331
		// All comparisons have been passed, so the two access policies are
332
		// equivalent
333
		return true;
334
	}
335

  
336
	public static void main(String[] args) throws Exception {
337

  
338
		ArrayList<String> guids = null;
339
		SyncAccessPolicy syncAP = new SyncAccessPolicy();
340

  
341
		// set up the properties based on the test/deployed configuration of the
342
		// workspace
343
		SortedProperties testProperties = new SortedProperties(
344
				"test/test.properties");
345
		testProperties.load();
346
		String metacatContextDir = testProperties
347
				.getProperty("metacat.contextDir");
348
		PropertyService.getInstance(metacatContextDir + "/WEB-INF");
349

  
350
		if (args.length > 0) {
351
			try {
352
				guids = new ArrayList<String>(Arrays.asList(args[0]
353
						.split("\\s*,\\s*")));
354
				System.out.println("Trying to syncing access policy for pids: "
355
						+ args[0]);
356
				syncAP.sync(guids);
357
			} catch (Exception e) {
358
				System.err.println("Error syncing pids: " + args[0]
359
						+ " Exception " + e.getMessage());
360
				System.exit(1);
361
			}
362
		}
363
	}
364
}

Also available in: Unified diff