Skip to content

Commit 070676f

Browse files
committed
Additional merge from master
Signed-off-by: Gary O'Neall <gary@sourceauditor.com>
2 parents 6595a27 + 6388208 commit 070676f

3 files changed

Lines changed: 290 additions & 8 deletions

File tree

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

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.slf4j.Logger;
3030
import org.slf4j.LoggerFactory;
3131
import org.spdx.core.InvalidSPDXAnalysisException;
32+
import org.spdx.core.SpdxIdNotFoundException;
3233
import org.spdx.library.model.v2.SpdxConstantsCompatV2;
3334
import org.spdx.library.model.v2.SpdxModelFactoryCompatV2;
3435
import org.spdx.library.model.v2.license.SpdxListedLicense;
@@ -199,7 +200,13 @@ public boolean isSpdxListedExceptionId(String exceptionId) {
199200
* @throws InvalidSPDXAnalysisException
200201
*/
201202
public SpdxListedLicense getListedLicenseByIdCompatV2(String licenseId) throws InvalidSPDXAnalysisException {
202-
return (SpdxListedLicense)SpdxModelFactoryCompatV2.createModelObjectV2(this.licenseStoreV2, SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX, licenseId, SpdxConstantsCompatV2.CLASS_SPDX_LISTED_LICENSE, null);
203+
try {
204+
return (SpdxListedLicense)SpdxModelFactoryCompatV2.getModelObjectV2(this.licenseStoreV2,
205+
SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX, licenseId,
206+
SpdxConstantsCompatV2.CLASS_SPDX_LISTED_LICENSE, null, false);
207+
} catch (SpdxIdNotFoundException ex) {
208+
return null;
209+
}
203210
}
204211

205212
/**
@@ -208,7 +215,13 @@ public SpdxListedLicense getListedLicenseByIdCompatV2(String licenseId) throws I
208215
* @throws InvalidSPDXAnalysisException
209216
*/
210217
public org.spdx.library.model.v2.license.ListedLicenseException getListedExceptionByIdCompatV2(String exceptionId) throws InvalidSPDXAnalysisException {
211-
return (org.spdx.library.model.v2.license.ListedLicenseException)SpdxModelFactoryCompatV2.createModelObjectV2(this.licenseStoreV2, SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX, exceptionId, SpdxConstantsCompatV2.CLASS_SPDX_LISTED_LICENSE_EXCEPTION, null);
218+
try {
219+
return (org.spdx.library.model.v2.license.ListedLicenseException)SpdxModelFactoryCompatV2.getModelObjectV2(
220+
this.licenseStoreV2, SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX,
221+
exceptionId, SpdxConstantsCompatV2.CLASS_SPDX_LISTED_LICENSE_EXCEPTION, null, false);
222+
} catch (SpdxIdNotFoundException ex) {
223+
return null;
224+
}
212225
}
213226

214227
/**
@@ -217,13 +230,23 @@ public org.spdx.library.model.v2.license.ListedLicenseException getListedExcepti
217230
* @throws InvalidSPDXAnalysisException
218231
*/
219232
public ListedLicense getListedLicenseById(String licenseId) throws InvalidSPDXAnalysisException {
220-
return new ListedLicense(this.licenseStoreV3, SpdxListedLicenseModelStore.licenseOrExceptionIdToObjectUri(licenseId), null,
221-
true, SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX);
233+
try {
234+
return new ListedLicense(this.licenseStoreV3, SpdxListedLicenseModelStore.licenseOrExceptionIdToObjectUri(licenseId), null,
235+
false, SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX);
236+
} catch (SpdxIdNotFoundException ex) {
237+
return null;
238+
}
239+
222240
}
223241

224242
public ListedLicenseException getListedExceptionById(String exceptionId) throws InvalidSPDXAnalysisException {
225-
return new ListedLicenseException(this.licenseStoreV3, SpdxListedLicenseModelStore.licenseOrExceptionIdToObjectUri(exceptionId), null,
226-
true, SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX);
243+
try {
244+
return new ListedLicenseException(this.licenseStoreV3, SpdxListedLicenseModelStore.licenseOrExceptionIdToObjectUri(exceptionId), null,
245+
false, SpdxConstantsCompatV2.LISTED_LICENSE_NAMESPACE_PREFIX);
246+
} catch (SpdxIdNotFoundException ex) {
247+
return null;
248+
}
249+
227250
}
228251

229252
/**
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
/**
2+
* Copyright (c) 2019 Source Auditor Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.spdx.library.model.license;
19+
20+
import java.util.List;
21+
import java.util.Objects;
22+
import java.util.Optional;
23+
import java.util.concurrent.locks.ReadWriteLock;
24+
import java.util.concurrent.locks.ReentrantReadWriteLock;
25+
26+
import org.slf4j.Logger;
27+
import org.slf4j.LoggerFactory;
28+
import org.spdx.Configuration;
29+
import org.spdx.library.InvalidSPDXAnalysisException;
30+
import org.spdx.library.SpdxConstants;
31+
import org.spdx.library.model.SpdxIdNotFoundException;
32+
import org.spdx.library.model.SpdxModelFactory;
33+
import org.spdx.storage.IModelStore;
34+
import org.spdx.storage.listedlicense.IListedLicenseStore;
35+
import org.spdx.storage.listedlicense.SpdxListedLicenseLocalStore;
36+
import org.spdx.storage.listedlicense.SpdxListedLicenseWebStore;
37+
38+
/**
39+
* Singleton class which holds the listed licenses
40+
*
41+
* @author Gary O'Neall
42+
*
43+
*/
44+
public class ListedLicenses {
45+
46+
static final Logger logger = LoggerFactory.getLogger(ListedLicenses.class.getName());
47+
48+
boolean onlyUseLocalLicenses;
49+
private IListedLicenseStore licenseModelStore;
50+
private static ListedLicenses listedLicenses = null;
51+
/**
52+
* Lock for any modifications to the underlying licenseModelStore
53+
*/
54+
private static final ReadWriteLock listedLicenseModificationLock = new ReentrantReadWriteLock();
55+
56+
/**
57+
* This constructor should only be called by the getListedLicenses method
58+
*/
59+
private ListedLicenses() {
60+
// Note: this code is confusing as this property changed names several times over time, and we want to preserve
61+
// backwards compatibility for those downstream library users who are using the old/deprecated names
62+
onlyUseLocalLicenses = Boolean.parseBoolean(Configuration.getInstance().getProperty("org.spdx.useJARLicenseInfoOnly",
63+
Configuration.getInstance().getProperty("SPDXParser.OnlyUseLocalLicenses",
64+
Configuration.getInstance().getProperty("OnlyUseLocalLicenses", "false"))));
65+
initializeLicenseModelStore();
66+
}
67+
68+
/**
69+
* This constructor should only be called by the initializeListedLicenses method,
70+
* to programmatically configure licenseModelStore from the application consuming this library
71+
*/
72+
private ListedLicenses(IListedLicenseStore licenseModelStore) {
73+
this.licenseModelStore = licenseModelStore;
74+
}
75+
76+
private void initializeLicenseModelStore() {
77+
listedLicenseModificationLock.writeLock().lock();
78+
try {
79+
if (!this.onlyUseLocalLicenses) {
80+
try {
81+
licenseModelStore = new SpdxListedLicenseWebStore();
82+
} catch(InvalidSPDXAnalysisException ex) {
83+
logger.error("Unable to access the most current listed licenses from https://spdx.org/licenses - using locally cached licenses: "+ex.getMessage(), ex);
84+
licenseModelStore = null;
85+
}
86+
}
87+
if (licenseModelStore == null) {
88+
try {
89+
licenseModelStore = new SpdxListedLicenseLocalStore();
90+
} catch(InvalidSPDXAnalysisException ex) {
91+
logger.error("Error loading cached SPDX licenses", ex);
92+
throw new RuntimeException("Unexpected error loading SPDX Listed Licenses", ex);
93+
}
94+
}
95+
} finally {
96+
listedLicenseModificationLock.writeLock().unlock();
97+
}
98+
}
99+
100+
public static ListedLicenses getListedLicenses() {
101+
ListedLicenses retval = null;
102+
listedLicenseModificationLock.readLock().lock();
103+
try {
104+
retval = listedLicenses;
105+
} finally {
106+
listedLicenseModificationLock.readLock().unlock();
107+
}
108+
if (Objects.isNull(retval)) {
109+
listedLicenseModificationLock.writeLock().lock();
110+
try {
111+
if (listedLicenses == null) {
112+
listedLicenses = new ListedLicenses();
113+
}
114+
retval = listedLicenses;
115+
} finally {
116+
listedLicenseModificationLock.writeLock().unlock();
117+
}
118+
}
119+
return retval;
120+
}
121+
122+
/**
123+
* Initializes the listed licenses singleton from a provided cache. This will
124+
* ignore all configuration around fetching remote licenses.
125+
*
126+
* @param licenseStore a preconfigured licenseStore, see {@link SpdxListedLicenseLocalStore} for
127+
* an example.
128+
* @return a singleton instance
129+
*/
130+
public static ListedLicenses initializeListedLicenses(IListedLicenseStore licenseStore) {
131+
listedLicenseModificationLock.writeLock().lock();
132+
try {
133+
listedLicenses = new ListedLicenses(licenseStore);
134+
return listedLicenses;
135+
} finally {
136+
listedLicenseModificationLock.writeLock().unlock();
137+
}
138+
}
139+
140+
/**
141+
* Resets all of the cached license information and reloads the license IDs
142+
* NOTE: This method should be used with caution, it will negatively impact
143+
* performance.
144+
* @return
145+
*/
146+
public static ListedLicenses resetListedLicenses() {
147+
listedLicenseModificationLock.writeLock().lock();
148+
try {
149+
listedLicenses = new ListedLicenses();
150+
return listedLicenses;
151+
} finally {
152+
listedLicenseModificationLock.writeLock().unlock();
153+
}
154+
}
155+
156+
157+
/**
158+
* @param licenseId case insensitive
159+
* @return true if the licenseId belongs to an SPDX listed license
160+
*/
161+
public boolean isSpdxListedLicenseId(String licenseId) {
162+
return this.licenseModelStore.isSpdxListedLicenseId(SpdxConstants.LISTED_LICENSE_URL, licenseId);
163+
}
164+
165+
/**
166+
* @param exceptionId case insensitive
167+
* @return true if the exceptionId belongs to an SPDX listed exception
168+
*/
169+
public boolean isSpdxListedExceptionId(String exceptionId) {
170+
return this.licenseModelStore.isSpdxListedExceptionId(SpdxConstants.LISTED_LICENSE_URL, exceptionId);
171+
}
172+
173+
/**
174+
* @param licenseId SPDX Listed License ID
175+
* @return SPDX listed license or null if the ID is not in the SPDX license list
176+
* @throws InvalidSPDXAnalysisException
177+
*/
178+
public SpdxListedLicense getListedLicenseById(String licenseId) throws InvalidSPDXAnalysisException {
179+
try {
180+
return (SpdxListedLicense) SpdxModelFactory.getModelObject(this.licenseModelStore, SpdxConstants.LISTED_LICENSE_URL, licenseId, SpdxConstants.CLASS_SPDX_LISTED_LICENSE, null, false);
181+
} catch (SpdxIdNotFoundException ex) {
182+
return null;
183+
}
184+
}
185+
186+
public ListedLicenseException getListedExceptionById(String exceptionId) throws InvalidSPDXAnalysisException {
187+
try {
188+
return (ListedLicenseException) SpdxModelFactory.getModelObject(this.licenseModelStore, SpdxConstants.LISTED_LICENSE_URL, exceptionId, SpdxConstants.CLASS_SPDX_LISTED_LICENSE_EXCEPTION, null, false);
189+
} catch (SpdxIdNotFoundException ex) {
190+
return null;
191+
}
192+
}
193+
194+
/**
195+
* @return List of all SPDX listed license IDs
196+
*/
197+
public List<String> getSpdxListedLicenseIds() {
198+
listedLicenseModificationLock.readLock().lock();
199+
try {
200+
return this.licenseModelStore.getSpdxListedLicenseIds();
201+
} finally {
202+
listedLicenseModificationLock.readLock().unlock();
203+
}
204+
}
205+
206+
/**
207+
* @return The version of the loaded license list in the form M.N, where M is the major release and N is the minor release.
208+
* If no license list is loaded, returns {@link org.spdx.storage.listedlicense.SpdxListedLicenseModelStore#DEFAULT_LICENSE_LIST_VERSION}.
209+
*/
210+
public String getLicenseListVersion() {
211+
return this.licenseModelStore.getLicenseListVersion();
212+
}
213+
214+
/**
215+
* @return list of SPDX exception IDs
216+
*/
217+
public List<String> getSpdxListedExceptionIds() {
218+
return this.licenseModelStore.getSpdxListedExceptionIds();
219+
}
220+
221+
/**
222+
* @param licenseId case insensitive license ID
223+
* @return the case sensitive license ID
224+
*/
225+
public Optional<String> listedLicenseIdCaseSensitive(String licenseId) {
226+
return this.licenseModelStore.listedLicenseIdCaseSensitive(licenseId);
227+
}
228+
229+
/**
230+
* @param exceptionId case insensitive exception ID
231+
* @return case sensitive ID
232+
*/
233+
public Optional<String> listedExceptionIdCaseSensitive(String exceptionId) {
234+
return this.licenseModelStore.listedExceptionIdCaseSensitive(exceptionId);
235+
}
236+
237+
/**
238+
* @return model store for listed licenses
239+
*/
240+
public IModelStore getLicenseModelStore() {
241+
return this.licenseModelStore;
242+
}
243+
244+
}

src/test/java/org/spdx/library/ListedLicensesTest.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
import org.spdx.core.InvalidSPDXAnalysisException;
66
import org.spdx.library.model.v2.SpdxConstantsCompatV2;
77
import org.spdx.library.model.v2.license.LicenseException;
8-
import org.spdx.library.model.v2.license.ListedLicenseException;
98
import org.spdx.library.model.v2.license.SpdxListedLicense;
9+
import org.spdx.library.model.v3.expandedlicensing.ListedLicense;
10+
import org.spdx.library.model.v3.expandedlicensing.ListedLicenseException;
1011
import org.spdx.storage.CompatibleModelStoreWrapper;
1112

1213
import junit.framework.TestCase;
@@ -72,6 +73,12 @@ public void testGetListedLicenseById() throws InvalidSPDXAnalysisException {
7273
assertEquals(id, result.getLicenseId());
7374
}
7475

76+
public void testGetListedLicenseByIdReturnsNull() throws InvalidSPDXAnalysisException {
77+
String id = "XXXX";
78+
ListedLicense result = ListedLicenses.getListedLicenses().getListedLicenseById(id);
79+
assertNull(result);
80+
}
81+
7582
public void testGetLicenseIbyIdLocal() throws InvalidSPDXAnalysisException {
7683
System.setProperty("SPDXParser.OnlyUseLocalLicenses", "true");
7784
ListedLicenses.resetListedLicenses();
@@ -101,6 +108,14 @@ public void testGetListedExceptionById() throws InvalidSPDXAnalysisException {
101108
assertEquals(id, result.getLicenseExceptionId());
102109
}
103110

111+
public void testGetListedExceptionByIdReturnsNull() throws InvalidSPDXAnalysisException {
112+
ListedLicenses.resetListedLicenses();
113+
String id = "XXXX";
114+
assertFalse(ListedLicenses.getListedLicenses().isSpdxListedExceptionId(id));
115+
ListedLicenseException result = ListedLicenses.getListedLicenses().getListedExceptionById(id);
116+
assertNull(result);
117+
}
118+
104119
public void testGetExceptionbyIdLocal() throws InvalidSPDXAnalysisException {
105120
System.setProperty("SPDXParser.OnlyUseLocalLicenses", "true");
106121
ListedLicenses.resetListedLicenses();
@@ -145,7 +160,7 @@ public void testGetLicenseIdProperty() throws InvalidSPDXAnalysisException {
145160

146161
public void testGetExceptionIdProperty() throws InvalidSPDXAnalysisException {
147162
String id = "Classpath-exception-2.0";
148-
ListedLicenseException ex = ListedLicenses.getListedLicenses().getListedExceptionByIdCompatV2(id);
163+
org.spdx.library.model.v2.license.ListedLicenseException ex = ListedLicenses.getListedLicenses().getListedExceptionByIdCompatV2(id);
149164
Optional<Object> idProp = ex.getModelStore().getValue(
150165
CompatibleModelStoreWrapper.documentUriIdToUri(ex.getDocumentUri(), id, false), SpdxConstantsCompatV2.PROP_LICENSE_EXCEPTION_ID);
151166
assertTrue(idProp.isPresent());

0 commit comments

Comments
 (0)