Project

General

Profile

1
package eu.dnetlib.enabling.is.registry; // NOPMD
2

    
3
import java.io.IOException;
4
import java.util.Date;
5
import java.util.List;
6
import java.util.UUID;
7
import javax.jws.WebService;
8
import javax.xml.parsers.ParserConfigurationException;
9
import javax.xml.xpath.XPath;
10
import javax.xml.xpath.XPathConstants;
11
import javax.xml.xpath.XPathExpressionException;
12
import javax.xml.xpath.XPathFactory;
13

    
14
import eu.dnetlib.DnetConstants;
15
import eu.dnetlib.enabling.is.registry.schema.OpaqueResourceValidator;
16
import eu.dnetlib.enabling.is.registry.schema.ValidationException;
17
import eu.dnetlib.enabling.is.registry.validation.ProfileValidationStrategy;
18
import eu.dnetlib.enabling.is.registry.validation.RegistrationPhase;
19
import eu.dnetlib.enabling.is.store.ISStore;
20
import eu.dnetlib.enabling.is.store.ISStoreException;
21
import eu.dnetlib.enabling.tools.*;
22
import eu.dnetlib.miscutils.functional.hash.Hashing;
23
import eu.dnetlib.rmi.common.APIDeprecatedException;
24
import eu.dnetlib.rmi.common.UnimplementedException;
25
import eu.dnetlib.rmi.enabling.*;
26
import org.apache.commons.logging.Log;
27
import org.apache.commons.logging.LogFactory;
28
import org.springframework.beans.factory.annotation.Autowired;
29
import org.springframework.beans.factory.annotation.Required;
30
import org.w3c.dom.Element;
31
import org.xml.sax.SAXException;
32

    
33
/**
34
 * Registry service implementation.
35
 * 
36
 * @author marko
37
 * 
38
 */
39
@WebService(targetNamespace = "http://services.dnetlib.eu/")
40
public class ISRegistryServiceImpl extends AbstractBaseService implements ISRegistryService { // NOPMD by marko on
41

    
42
	/**
43
	 * logger.
44
	 */
45
	private static final Log log = LogFactory.getLog(ISRegistryServiceImpl.class); // NOPMD by marko on 11/24/08 5:02 PM
46

    
47
	/**
48
	 * error message: secure profile registration.
49
	 */
50
	private static final String ERROR_SEC_PROFILE = "cannot register secure profile";
51

    
52
	/**
53
	 * error message: trying to retrieve the current stored version of the resource profile.
54
	 */
55
	private static final String CANT_FETCH = "cannot fetch original profile";
56

    
57
	/**
58
	 * error message: cannot create a resource.
59
	 */
60
	private static final String CANT_CREATE = "cannot create resource";
61

    
62
	/**
63
	 * IS Store
64
	 */
65
	private ISStore isStore;
66

    
67
	/**
68
	 * IS Lookup
69
	 */
70
	private ISLookUpService isLookup;
71

    
72

    
73

    
74
	/**
75
	 * manages the pending state of resource. Different implementations can be plugged in.
76
	 */
77
	private PendingResourceManager pendingManager = new CompatPendingResourceManagerImpl();
78

    
79
	/**
80
	 * manages resource identifier mappings with the abstract xmldb namespace (files/collections).
81
	 */
82
	@Autowired
83
	private ResourceIdentifierResolver resIdResolver = new CompatResourceIdentifierResolverImpl();
84

    
85
	/**
86
	 * used to validate resources.
87
	 */
88
	private OpaqueResourceValidator resourceValidator;
89

    
90
	/**
91
	 * used to validate resources w.r.t. a set of defined properties.
92
	 */
93
	@Autowired
94
	private ProfileValidationStrategy profileValidationStrategy;
95

    
96
	/**
97
	 * query utils. Used to obtain xmldb collection names and other things useful for interacting with the IS_Store.
98
	 */
99
	private XQueryUtils xqueryUtils;
100

    
101
	/**
102
	 * the blackboard management stuff is factored out here.
103
	 */
104
	@Autowired
105
	private RegistryBlackboardManager blackboardManager;
106

    
107
	@Override
108
	public void start() {
109
		super.start();
110
	}
111

    
112
	/**
113
	 * {@inheritDoc}
114
	 * 
115
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#addBlackBoardMessage(java.lang.String, java.lang.String, java.lang.String)
116
	 */
117
	@Override
118
	public void addBlackBoardMessage(final String profId, final String messageId, final String message) throws ISRegistryException {
119
		blackboardManager.addMessage(profId, messageId, message);
120
	}
121

    
122
	/**
123
	 * {@inheritDoc}
124
	 * 
125
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#addOrUpdateResourceType(java.lang.String, java.lang.String)
126
	 */
127
	@Override
128
	public boolean addOrUpdateResourceType(final String resourceType, final String resourceSchema) throws ISRegistryException {
129
		return addResourceType(resourceType, resourceSchema);
130
	}
131

    
132
	/**
133
	 * {@inheritDoc}
134
	 * 
135
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#addProfileNode(java.lang.String, java.lang.String, java.lang.String)
136
	 */
137
	@Override
138
	public boolean addProfileNode(final String profId, final String xpath, final String node) throws ISRegistryException {
139
		// TODO Auto-generated method stub
140
		throw new UnimplementedException();
141
	}
142

    
143
	/**
144
	 * {@inheritDoc}
145
	 * 
146
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#addResourceType(java.lang.String, java.lang.String)
147
	 */
148
	@Override
149
	public boolean addResourceType(final String resourceType, final String resourceSchema) throws ISRegistryException {
150
		try {
151
			return isStore.insertXML(resourceType, xqueryUtils.getRootCollection() + DnetConstants.RESOURCE_TYPES,
152
					resourceSchema);
153
		} catch (ISStoreException e) {
154
			throw new ISRegistryException("cannot add resource type", e);
155
		}
156
	}
157

    
158
	/**
159
	 * {@inheritDoc}
160
	 * 
161
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#deleteBlackBoardMessage(java.lang.String, java.lang.String)
162
	 */
163
	@Override
164
	public void deleteBlackBoardMessage(final String profId, final String messageId) throws ISRegistryException {
165
		blackboardManager.deleteMessage(profId, messageId);
166
	}
167

    
168
	/**
169
	 * {@inheritDoc}
170
	 * 
171
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#deleteProfile(java.lang.String)
172
	 */
173
	@Override
174
	public boolean deleteProfile(final String resId) throws ISRegistryException {
175
		try {
176
			final boolean res = isStore.deleteXML(resIdResolver.getFileName(resId),
177
					"/db/DRIVER/" + resIdResolver.getCollectionName(resId));
178
			if (!res) { throw new ISRegistryDocumentNotFoundException("document " + resId + " not found"); }
179

    
180
			return true;
181
		} catch (ISStoreException e) {
182
			throw new ISRegistryException("cannot delete profile " + resId, e);
183
		}
184
	}
185

    
186
	/**
187
	 * {@inheritDoc}
188
	 * 
189
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#deleteProfiles(java.util.List)
190
	 */
191
	@Override
192
	public boolean deleteProfiles(final List<String> arrayprofId) throws ISRegistryException {
193
		throw new APIDeprecatedException();
194
	}
195

    
196
	/**
197
	 * {@inheritDoc}
198
	 * 
199
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#deleteResourceType(java.lang.String, java.lang.Boolean)
200
	 */
201
	@Override
202
	public boolean deleteResourceType(final String resourceType, final Boolean hierarchical) throws ISRegistryException {
203
		try {
204
			return isStore.deleteXML(resourceType, xqueryUtils.getRootCollection() + DnetConstants.RESOURCE_TYPES);
205
		} catch (ISStoreException e) {
206
			throw new ISRegistryException("error deleting resource type " + resourceType, e);
207
		}
208
	}
209

    
210
	/**
211
	 * {@inheritDoc}
212
	 * 
213
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#executeXUpdate(java.lang.String)
214
	 */
215
	@Override
216
	public boolean executeXUpdate(final String xquery) throws ISRegistryException {
217
		try {
218
			return isStore.executeXUpdate(xquery);
219
		} catch (ISStoreException e) {
220
			throw new ISRegistryException(e);
221
		}
222
	}
223

    
224
	/**
225
	 * {@inheritDoc}
226
	 * 
227
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#insertProfileForValidation(java.lang.String, java.lang.String)
228
	 */
229
	@Override
230
	public String insertProfileForValidation(final String resourceType, final String resourceProfile) throws ISRegistryException {
231
		try {
232
			final OpaqueResource resource = new StringOpaqueResource(resourceProfile);
233
			if (!resourceType.equals(resource.getResourceType())) { throw new ISRegistryException("expected resource type doesn't match to resource"); }
234

    
235
			pendingManager.setPending(resource, true);
236

    
237
			return registerProfile(resource.asString());
238
		} catch (XPathExpressionException e) {
239
			throw new ISRegistryException(e);
240
		} catch (SAXException e) {
241
			throw new ISRegistryException(e);
242
		} catch (IOException e) {
243
			throw new ISRegistryException(e);
244
		} catch (ParserConfigurationException e) {
245
			throw new ISRegistryException(e);
246
		}
247
	}
248

    
249
	/**
250
	 * {@inheritDoc}
251
	 * 
252
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#refreshProfile(java.lang.String, java.lang.String)
253
	 */
254
	@Override
255
	public boolean refreshProfile(final String profId, final String resourceType) throws ISRegistryException {
256
		// TODO Auto-generated method stub
257
		throw new UnimplementedException();
258
	}
259

    
260
	/**
261
	 * {@inheritDoc}
262
	 * 
263
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#registerProfile(java.lang.String)
264
	 */
265
	@Override
266
	public String registerProfile(final String resourceProfile) throws ISRegistryException {
267
		log.debug("registering profile");
268

    
269
		try {
270
			final OpaqueResource resource = new StringOpaqueResource(resourceProfile);
271

    
272
			// TODO: factor this out (possibly not within the OpaqueResource class)
273
			final String coll = xqueryUtils.getCollectionPath(resource);
274
			final String fileName = UUID.randomUUID().toString();
275
			final String newId = fileName + "_" + Hashing.encodeBase64(coll);
276
			resource.setResourceId(newId);
277

    
278
			resource.setModificationDate(new Date());
279

    
280
			// log.info("validating to xml schema: " + resource.asString());
281
			resourceValidator.validate(resource);
282

    
283
			profileValidationStrategy.accept(resource, RegistrationPhase.Register);
284

    
285
			// TODO: factor out ResourceType class
286
			isStore.insertXML(fileName, xqueryUtils.getRootCollection() + coll, resource.asString());
287

    
288
			return resource.getResourceId();
289
		} catch (XPathExpressionException e) {
290
			throw new ISRegistryException(e);
291
		} catch (SAXException e) {
292
			throw new ISRegistryException(e);
293
		} catch (IOException e) {
294
			throw new ISRegistryException(e);
295
		} catch (ParserConfigurationException e) {
296
			throw new ISRegistryException(e);
297
		} catch (ISStoreException e) {
298
			throw new ISRegistryException(e);
299
		} catch (ValidationException e) {
300
			throw new ISRegistryException("profile is not conforming to the schema: " + e.getMessage(), e);
301
		}
302
	}
303

    
304
	/**
305
	 * {@inheritDoc}
306
	 * 
307
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#registerSecureProfile(java.lang.String, java.lang.String)
308
	 */
309
	@Override
310
	public String registerSecureProfile(final String resourceProfId, final String secureProfId) throws ISRegistryException {
311
		try {
312
			synchronized (this) {
313
				final String secureProfSrc;
314
				try {
315
					secureProfSrc = isLookup.getResourceProfile(secureProfId); // NOPMD
316
				} catch (ISLookUpDocumentNotFoundException e) {
317
					throw new ISRegistryException("cannot register secure profile, the given secure profile doesn't exist", e);
318
				}
319
				final OpaqueResource secureProf = new StringOpaqueResource(secureProfSrc);
320

    
321
				final String profId = validateProfile(resourceProfId);
322

    
323
				final XPath xpath = XPathFactory.newInstance().newXPath();
324
				final Element idEl = (Element) xpath.evaluate("/RESOURCE_PROFILE/BODY/CONFIGURATION/resourceId", secureProf.asDom(), XPathConstants.NODE);
325
				idEl.setTextContent(profId);
326

    
327
				if (!updateProfile(secureProfId, secureProf.asString(), secureProf.getResourceType())) { throw new ISRegistryException(
328
						"cannot update security profile (updateProfile returned false)"); }
329

    
330
				return profId;
331
			}
332
		} catch (XPathExpressionException e) {
333
			throw new ISRegistryException(ERROR_SEC_PROFILE, e);
334
		} catch (SAXException e) {
335
			throw new ISRegistryException(ERROR_SEC_PROFILE, e);
336
		} catch (IOException e) {
337
			throw new ISRegistryException(ERROR_SEC_PROFILE, e);
338
		} catch (ParserConfigurationException e) {
339
			throw new ISRegistryException(ERROR_SEC_PROFILE, e);
340
		} catch (ISLookUpException e) {
341
			throw new ISRegistryException("cannot register secure profile, problem fetching the given secure profile", e);
342
		}
343
	}
344

    
345
	/**
346
	 * {@inheritDoc}
347
	 * 
348
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#removeProfileNode(java.lang.String, java.lang.String)
349
	 */
350
	@Override
351
	public boolean removeProfileNode(final String profId, final String nodeId) throws ISRegistryException {
352
		// TODO Auto-generated method stub
353
		throw new UnimplementedException();
354
	}
355

    
356
	/**
357
	 * {@inheritDoc}
358
	 * 
359
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#replyBlackBoardMessage(java.lang.String, java.lang.String)
360
	 */
361
	@Override
362
	public void replyBlackBoardMessage(final String profId, final String message) throws ISRegistryException {
363
		blackboardManager.replyMessage(profId, message);
364
	}
365

    
366
	/**
367
	 * {@inheritDoc}
368
	 * 
369
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#updateProfile(java.lang.String, java.lang.String, java.lang.String)
370
	 */
371
	@Override
372
	public boolean updateProfile(final String resId, final String resourceProfile, final String resourceType) throws ISRegistryException {
373
		try {
374
			final String fileName = resIdResolver.getFileName(resId);
375
			final String fileColl = "/db/DRIVER/" + resIdResolver.getCollectionName(resId);
376

    
377
			final String oldProfileSrc = isStore.getXML(fileName, fileColl);
378

    
379
			if (oldProfileSrc == null) { throw new ISRegistryException("cannot update a non existing profile " + resId); }
380

    
381
			final OpaqueResource oldResource = new StringOpaqueResource(oldProfileSrc);
382

    
383
			final StringOpaqueResource newResource = new StringOpaqueResource(resourceProfile);
384
			newResource.setResourceId(oldResource.getResourceId());
385
			newResource.setResourceKind(oldResource.getResourceKind());
386
			newResource.setResourceType(oldResource.getResourceType());
387
			newResource.setModificationDate(new Date());
388

    
389
			getResourceValidator().validate(newResource);
390

    
391
			return isStore.updateXML(fileName, fileColl, newResource.asString());
392
		} catch (ISStoreException e) {
393
			throw new ISRegistryException(e);
394
		} catch (XPathExpressionException e) {
395
			throw new ISRegistryException(e);
396
		} catch (ValidationException e) {
397
			throw new ISRegistryException("profile not conforming to xml schema", e);
398
		} catch (SAXException e) {
399
			throw new ISRegistryException(e);
400
		} catch (IOException e) {
401
			throw new ISRegistryException(e);
402
		} catch (ParserConfigurationException e) {
403
			throw new ISRegistryException(e);
404
		}
405
	}
406

    
407
	/**
408
	 * {@inheritDoc}
409
	 * 
410
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#updateProfileDHN(java.lang.String)
411
	 */
412
	@Override
413
	public String updateProfileDHN(final String resourceProfile) throws ISRegistryException {
414
		// TODO Auto-generated method stub
415
		throw new UnimplementedException();
416
	}
417

    
418
	/**
419
	 * {@inheritDoc}
420
	 * 
421
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#updateProfileNode(java.lang.String, java.lang.String, java.lang.String)
422
	 */
423
	@Override
424
	public boolean updateProfileNode(final String profId, final String xpath, final String node) throws ISRegistryException {
425
		return executeXUpdate("for $x in collection('/db/DRIVER')//RESOURCE_PROFILE[.//RESOURCE_IDENTIFIER/@value eq '" + profId + "']" + xpath
426
				+ " return update replace $x with " + node);
427
	}
428

    
429
	/**
430
	 * {@inheritDoc}
431
	 * 
432
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#updateRegionDescription(java.lang.String, java.lang.String)
433
	 */
434
	@Override
435
	public boolean updateRegionDescription(final String profId, final String resourceProfile) throws ISRegistryException {
436
		// TODO Auto-generated method stub
437
		throw new UnimplementedException();
438
	}
439

    
440
	/**
441
	 * {@inheritDoc}
442
	 * 
443
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#validateProfile(java.lang.String)
444
	 */
445
	@Override
446
	public String validateProfile(final String profId) throws ISRegistryException {
447
		try {
448
			final String resourceProfile = isLookup.getResourceProfile(profId);
449
			final OpaqueResource resource = new StringOpaqueResource(resourceProfile);
450
			pendingManager.setValid(resource);
451

    
452
			return resource.getResourceId();
453
		} catch (ISLookUpException e) {
454
			throw new ISRegistryException(CANT_FETCH, e);
455
		} catch (XPathExpressionException e) {
456
			throw new ISRegistryException(CANT_CREATE, e);
457
		} catch (SAXException e) {
458
			throw new ISRegistryException(CANT_CREATE, e);
459
		} catch (IOException e) {
460
			throw new ISRegistryException(CANT_CREATE, e);
461
		} catch (ParserConfigurationException e) {
462
			throw new ISRegistryException(CANT_CREATE, e);
463
		}
464
	}
465

    
466
	/**
467
	 * {@inheritDoc}
468
	 * 
469
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#invalidateProfile(java.lang.String)
470
	 */
471
	@Override
472
	public String invalidateProfile(final String profId) throws ISRegistryException {
473
		try {
474
			final String resourceProfile = isLookup.getResourceProfile(profId);
475
			final OpaqueResource resource = new StringOpaqueResource(resourceProfile);
476
			pendingManager.setPending(resource);
477

    
478
			return resource.getResourceId();
479
		} catch (ISLookUpException e) {
480
			throw new ISRegistryException(CANT_FETCH, e);
481
		} catch (XPathExpressionException e) {
482
			throw new ISRegistryException(CANT_CREATE, e);
483
		} catch (SAXException e) {
484
			throw new ISRegistryException(CANT_CREATE, e);
485
		} catch (IOException e) {
486
			throw new ISRegistryException(CANT_CREATE, e);
487
		} catch (ParserConfigurationException e) {
488
			throw new ISRegistryException(CANT_CREATE, e);
489
		}
490
	}
491

    
492
	/**
493
	 * {@inheritDoc}
494
	 *
495
	 * @see eu.dnetlib.rmi.enabling.ISRegistryService#validateProfile(String)
496
	 */
497
	@Override
498
	public List<String> validateProfiles(final List<String> profIds) throws ISRegistryException {
499
		throw new APIDeprecatedException();
500
	}
501

    
502

    
503
	public PendingResourceManager getPendingManager() {
504
		return pendingManager;
505
	}
506

    
507
	public void setPendingManager(final PendingResourceManager pendingManager) {
508
		this.pendingManager = pendingManager;
509
	}
510

    
511
	public ResourceIdentifierResolver getResIdResolver() {
512
		return resIdResolver;
513
	}
514

    
515
	public void setResIdResolver(final ResourceIdentifierResolver resIdResolver) {
516
		this.resIdResolver = resIdResolver;
517
	}
518

    
519
	public OpaqueResourceValidator getResourceValidator() {
520
		return resourceValidator;
521
	}
522

    
523
	@Required
524
	public void setResourceValidator(final OpaqueResourceValidator resourceValidator) {
525
		this.resourceValidator = resourceValidator;
526
	}
527

    
528
	public XQueryUtils getXqueryUtils() {
529
		return xqueryUtils;
530
	}
531

    
532
	@Required
533
	public void setXqueryUtils(final XQueryUtils xqueryUtils) {
534
		this.xqueryUtils = xqueryUtils;
535
	}
536

    
537
	public RegistryBlackboardManager getBlackboardManager() {
538
		return blackboardManager;
539
	}
540

    
541
	public void setBlackboardManager(final RegistryBlackboardManager blackboardManager) {
542
		this.blackboardManager = blackboardManager;
543
	}
544

    
545
	public ProfileValidationStrategy getProfileValidationStrategy() {
546
		return profileValidationStrategy;
547
	}
548

    
549
	public void setProfileValidationStrategy(final ProfileValidationStrategy profileValidationStrategy) {
550
		this.profileValidationStrategy = profileValidationStrategy;
551
	}
552

    
553
	public ISStore getIsStore() {
554
		return isStore;
555
	}
556

    
557
	@Required
558
	public void setIsStore(final ISStore isStore) {
559
		this.isStore = isStore;
560
	}
561

    
562
	public ISLookUpService getIsLookup() {
563
		return isLookup;
564
	}
565

    
566
	@Required
567
	public void setIsLookup(final ISLookUpService isLookup) {
568
		this.isLookup = isLookup;
569
	}
570

    
571
}
(3-3/11)