Skip to content

Commit f2086d2

Browse files
authored
Merge pull request #170 from spdx/issue167
Make ModelObject threadsafe on create and getObjectPropertyValue
2 parents da021df + 098cdcc commit f2086d2

2 files changed

Lines changed: 45 additions & 16 deletions

File tree

src/main/java/org/spdx/library/ModelCopyManager.java

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.spdx.library.model.SimpleUriValue;
3030
import org.spdx.library.model.TypedValue;
3131
import org.spdx.storage.IModelStore;
32+
import org.spdx.storage.IModelStore.IModelStoreLock;
3233
import org.spdx.storage.IModelStore.IdType;
3334

3435
/**
@@ -196,10 +197,17 @@ public void copy(IModelStore toStore, String toDocumentUri, String toId,
196197
*/
197198
private void copyIndividualProperty(IModelStore toStore, String toDocumentUri, String toId, IModelStore fromStore,
198199
String fromDocumentUri, String fromId, String propName, boolean excludeLicenseDetails) throws InvalidSPDXAnalysisException {
199-
if (fromStore.isCollectionProperty(fromDocumentUri, fromId, propName)) {
200-
throw new InvalidSPDXAnalysisException("Property "+propName+" is a collection type");
201-
}
202-
Optional<Object> result = fromStore.getValue(fromDocumentUri, fromId, propName);
200+
IModelStoreLock fromStoreLock = fromStore.enterCriticalSection(fromDocumentUri, false);
201+
//Note: we use a write lock since the RDF store may end up creating a property to check if it is a collection
202+
Optional<Object> result = Optional.empty();
203+
try {
204+
if (fromStore.isCollectionProperty(fromDocumentUri, fromId, propName)) {
205+
throw new InvalidSPDXAnalysisException("Property "+propName+" is a collection type");
206+
}
207+
result = fromStore.getValue(fromDocumentUri, fromId, propName);
208+
} finally {
209+
fromStoreLock.unlock();
210+
}
203211
if (result.isPresent()) {
204212
if (result.get() instanceof IndividualUriValue) {
205213
toStore.setValue(toDocumentUri, toId, propName, new SimpleUriValue((IndividualUriValue)result.get()));
@@ -232,10 +240,17 @@ private void copyIndividualProperty(IModelStore toStore, String toDocumentUri, S
232240
*/
233241
private void copyCollectionProperty(IModelStore toStore, String toDocumentUri, String toId, IModelStore fromStore,
234242
String fromDocumentUri, String fromId, String propName, boolean excludeLicenseDetails) throws InvalidSPDXAnalysisException {
235-
if (!fromStore.isCollectionProperty(fromDocumentUri, fromId, propName)) {
236-
throw new InvalidSPDXAnalysisException("Property "+propName+" is not a collection type");
237-
}
238-
Iterator<Object> fromListIter = fromStore.listValues(fromDocumentUri, fromId, propName);
243+
IModelStoreLock fromStoreLock = fromStore.enterCriticalSection(fromDocumentUri, false);
244+
//Note: we use a write lock since the RDF store may end up creating a property to check if it is a collection
245+
Iterator<Object> fromListIter = null;
246+
try {
247+
if (!fromStore.isCollectionProperty(fromDocumentUri, fromId, propName)) {
248+
throw new InvalidSPDXAnalysisException("Property "+propName+" is not a collection type");
249+
}
250+
fromListIter = fromStore.listValues(fromDocumentUri, fromId, propName);
251+
} finally {
252+
fromStoreLock.unlock();
253+
}
239254
while (fromListIter.hasNext()) {
240255
Object listItem = fromListIter.next();
241256
Object toStoreItem;

src/main/java/org/spdx/library/model/ModelObject.java

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,15 @@ public ModelObject(IModelStore modelStore, String documentUri, String id, @Nulla
201201
}
202202
} else {
203203
if (create) {
204-
modelStore.create(documentUri, id, getType());
204+
IModelStoreLock lock = enterCriticalSection(false);
205+
// re-check since previous check was done outside of the lock
206+
try {
207+
if (!modelStore.exists(documentUri, id)) {
208+
modelStore.create(documentUri, id, getType());
209+
}
210+
} finally {
211+
lock.unlock();
212+
}
205213
} else {
206214
throw new SpdxIdNotFoundException(id+" does not exist in document "+documentUri);
207215
}
@@ -337,13 +345,19 @@ protected Optional<Object> getObjectPropertyValue(String propertyName) throws In
337345
*/
338346
protected static Optional<Object> getObjectPropertyValue(IModelStore stModelStore, String stDocumentUri,
339347
String stId, String propertyName, ModelCopyManager copyManager) throws InvalidSPDXAnalysisException {
340-
if (!stModelStore.exists(stDocumentUri, stId)) {
341-
return Optional.empty();
342-
} else if (stModelStore.isCollectionProperty(stDocumentUri, stId, propertyName)) {
343-
return Optional.of(new ModelCollection<>(stModelStore, stDocumentUri, stId, propertyName, copyManager, null));
344-
} else {
345-
return ModelStorageClassConverter.optionalStoredObjectToModelObject(stModelStore.getValue(stDocumentUri, stId, propertyName),
346-
stDocumentUri, stModelStore, copyManager);
348+
IModelStoreLock lock = stModelStore.enterCriticalSection(stDocumentUri, false);
349+
// NOTE: we use a write lock since the ModelStorageClassConverter may end up creating objects in the store
350+
try {
351+
if (!stModelStore.exists(stDocumentUri, stId)) {
352+
return Optional.empty();
353+
} else if (stModelStore.isCollectionProperty(stDocumentUri, stId, propertyName)) {
354+
return Optional.of(new ModelCollection<>(stModelStore, stDocumentUri, stId, propertyName, copyManager, null));
355+
} else {
356+
return ModelStorageClassConverter.optionalStoredObjectToModelObject(stModelStore.getValue(stDocumentUri, stId, propertyName),
357+
stDocumentUri, stModelStore, copyManager);
358+
}
359+
} finally {
360+
lock.unlock();
347361
}
348362
}
349363

0 commit comments

Comments
 (0)