This is an automated email from the ASF dual-hosted git repository. madhan pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/atlas.git
The following commit(s) were added to refs/heads/master by this push: new 43daa256d ATLAS-4652: fix to address potential NPE in AtlasAttributeDef.isSoftReferenced() 43daa256d is described below commit 43daa256dd04a2e9167de6749f34e262b8216de3 Author: Madhan Neethiraj <mad...@apache.org> AuthorDate: Sat Oct 1 17:45:27 2022 -0700 ATLAS-4652: fix to address potential NPE in AtlasAttributeDef.isSoftReferenced() --- .../apache/atlas/model/typedef/AtlasStructDef.java | 6 +- .../org/apache/atlas/utils/AtlasStringUtil.java | 43 +++++++ .../apache/atlas/utils/AtlasStringUtilTest.java | 127 +++++++++++++++++++++ .../atlas/repository/impexp/ImportService.java | 12 +- .../store/graph/v2/BulkImporterImpl.java | 4 +- .../store/graph/v2/bulkimport/MigrationImport.java | 3 +- 6 files changed, 183 insertions(+), 12 deletions(-) diff --git a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasStructDef.java b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasStructDef.java index a621fb0b5..bef850c3e 100644 --- a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasStructDef.java +++ b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasStructDef.java @@ -515,9 +515,9 @@ public class AtlasStructDef extends AtlasBaseTypeDef implements Serializable { @JsonIgnore public boolean isSoftReferenced() { - return this.options != null && - getOptions().containsKey(AtlasAttributeDef.ATTRDEF_OPTION_SOFT_REFERENCE) && - getOptions().get(AtlasAttributeDef.ATTRDEF_OPTION_SOFT_REFERENCE).equals(STRING_TRUE); + String val = getOption(AtlasAttributeDef.ATTRDEF_OPTION_SOFT_REFERENCE); + + return val != null && Boolean.valueOf(val); } @JsonIgnore diff --git a/intg/src/main/java/org/apache/atlas/utils/AtlasStringUtil.java b/intg/src/main/java/org/apache/atlas/utils/AtlasStringUtil.java new file mode 100644 index 000000000..11a439921 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/utils/AtlasStringUtil.java @@ -0,0 +1,43 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.atlas.utils; + +import java.util.Map; +import java.util.Objects; + +public class AtlasStringUtil { + public static boolean hasOption(Map<String, String> options, String optionName) { + return options != null && options.containsKey(optionName); + } + + public static String getOption(Map<String, String> options, String optionName) { + return options != null ? options.get(optionName) : null; + } + + public static boolean getBooleanOption(Map<String, String> options, String optionName) { + return options != null && Boolean.parseBoolean(options.get(optionName)); + } + + public static boolean getBooleanOption(Map<String, String> options, String optionName, boolean defaultValue) { + return (options != null && options.containsKey(optionName)) ? Boolean.parseBoolean(options.get(optionName)) : defaultValue; + } + + public static boolean optionEquals(Map<String, String> options, String optionName, String value) { + return Objects.equals(options != null ? options.get(optionName) : null, value); + } +} diff --git a/intg/src/test/java/org/apache/atlas/utils/AtlasStringUtilTest.java b/intg/src/test/java/org/apache/atlas/utils/AtlasStringUtilTest.java new file mode 100644 index 000000000..da77645d9 --- /dev/null +++ b/intg/src/test/java/org/apache/atlas/utils/AtlasStringUtilTest.java @@ -0,0 +1,127 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.atlas.utils; + +import org.testng.annotations.Test; + +import java.util.Collections; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +public class AtlasStringUtilTest { + @Test + public void testGetOption() { + // null options + assertNull(AtlasStringUtil.getOption(null, "opt")); + + // null optionName + assertNull(AtlasStringUtil.getOption(Collections.emptyMap(), null)); + + // explicit null value for the option + assertNull(AtlasStringUtil.getOption(Collections.singletonMap("opt", null), null)); + + // option not present + assertNull(AtlasStringUtil.getOption(Collections.emptyMap(), "opt")); + assertNull(AtlasStringUtil.getOption(Collections.singletonMap("opt", "val"), "opt1")); + + // option present + assertEquals(AtlasStringUtil.getOption(Collections.singletonMap("opt", "val"), "opt"), "val"); + assertNotEquals(AtlasStringUtil.getOption(Collections.singletonMap("opt", "val"), "opt"), "val1"); + } + + @Test + public void testGetBooleanOption() { + // null options + assertFalse(AtlasStringUtil.getBooleanOption(null, "opt")); + + // null optionName + assertFalse(AtlasStringUtil.getBooleanOption(Collections.emptyMap(), null)); + + // explicit null value for the option + assertFalse(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", null), "opt")); + + // option not present + assertFalse(AtlasStringUtil.getBooleanOption(Collections.emptyMap(), "opt")); + assertFalse(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", "val"), "opt1")); + + // invalid value for the option + assertFalse(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", "val"), "opt")); + + // option present + assertFalse(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", "false"), "opt")); + assertTrue(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", "true"), "opt")); + assertTrue(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", "TRUE"), "opt")); + } + + @Test + public void testGetBooleanOptionWithDefault() { + // null options + assertTrue(AtlasStringUtil.getBooleanOption(null, "opt", true)); + assertFalse(AtlasStringUtil.getBooleanOption(null, "opt", false)); + + // null optionName + assertTrue(AtlasStringUtil.getBooleanOption(Collections.emptyMap(), null, true)); + assertFalse(AtlasStringUtil.getBooleanOption(Collections.emptyMap(), null, false)); + + // explicit null value for the option + assertFalse(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", null), "opt", false)); + assertFalse(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", null), "opt", true)); + + // option not present + assertTrue(AtlasStringUtil.getBooleanOption(Collections.emptyMap(), "opt", true)); + assertFalse(AtlasStringUtil.getBooleanOption(Collections.emptyMap(), "opt", false)); + assertTrue(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", "val"), "opt1", true)); + assertFalse(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", "val"), "opt1", false)); + + // invalid value for the option + assertFalse(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", "val"), "opt", true)); + assertFalse(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", "val"), "opt", false)); + + // valid value for the option + assertFalse(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", "false"), "opt", true)); + assertTrue(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", "true"), "opt", true)); + assertTrue(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", "TRUE"), "opt", true)); + assertTrue(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", "true"), "opt", false)); + assertTrue(AtlasStringUtil.getBooleanOption(Collections.singletonMap("opt", "TRUE"), "opt", false)); + } + + @Test + public void testOptionEquals() { + // null options + assertTrue(AtlasStringUtil.optionEquals(null, "opt", null)); + assertFalse(AtlasStringUtil.optionEquals(null, "opt", "val")); + + // null optionName + assertTrue(AtlasStringUtil.optionEquals(Collections.emptyMap(), null, null)); + + // explicit null value for the option + assertTrue(AtlasStringUtil.optionEquals(Collections.singletonMap("opt", null), "opt", null)); + + // option not present + assertTrue(AtlasStringUtil.optionEquals(Collections.emptyMap(), "opt", null)); + assertTrue(AtlasStringUtil.optionEquals(Collections.singletonMap("opt", "val"), "opt1", null)); + + // option present + assertTrue(AtlasStringUtil.optionEquals(Collections.singletonMap("opt", "val"), "opt", "val")); + assertFalse(AtlasStringUtil.optionEquals(Collections.singletonMap("opt", "val"), "opt", "val1")); + } +} diff --git a/repository/src/main/java/org/apache/atlas/repository/impexp/ImportService.java b/repository/src/main/java/org/apache/atlas/repository/impexp/ImportService.java index 1d29bf833..ad4672d78 100644 --- a/repository/src/main/java/org/apache/atlas/repository/impexp/ImportService.java +++ b/repository/src/main/java/org/apache/atlas/repository/impexp/ImportService.java @@ -34,6 +34,7 @@ import org.apache.atlas.repository.store.graph.v2.EntityImportStream; import org.apache.atlas.store.AtlasTypeDefStore; import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasTypeRegistry; +import org.apache.atlas.utils.AtlasStringUtil; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.MapUtils; import org.apache.commons.lang3.StringUtils; @@ -106,10 +107,10 @@ public class ImportService { RequestContext.get().setImportInProgress(true); - String transforms = MapUtils.isNotEmpty(request.getOptions()) ? request.getOptions().get(TRANSFORMS_KEY) : null; + String transforms = AtlasStringUtil.getOption(request.getOptions(), TRANSFORMS_KEY); setImportTransform(source, transforms); - String transformers = MapUtils.isNotEmpty(request.getOptions()) ? request.getOptions().get(TRANSFORMERS_KEY) : null; + String transformers = AtlasStringUtil.getOption(request.getOptions(), TRANSFORMERS_KEY); setEntityTransformerHandlers(source, transformers); startTimestamp = System.currentTimeMillis(); @@ -254,9 +255,8 @@ public class ImportService { private EntityImportStream createZipSource(AtlasImportRequest request, InputStream inputStream, String configuredTemporaryDirectory) throws AtlasBaseException { try { - if (isMigrationMode(request) || (request.getOptions().containsKey(AtlasImportRequest.OPTION_KEY_FORMAT) && - request.getOptions().get(AtlasImportRequest.OPTION_KEY_FORMAT).equals(AtlasImportRequest.OPTION_KEY_FORMAT_ZIP_DIRECT))) { - LOG.info("ZipSource Format: ZipDirect: Size: {}", request.getOptions().get("size")); + if (isMigrationMode(request) || AtlasStringUtil.optionEquals(request.getOptions(), AtlasImportRequest.OPTION_KEY_FORMAT, AtlasImportRequest.OPTION_KEY_FORMAT_ZIP_DIRECT)) { + LOG.info("ZipSource Format: ZipDirect: Size: {}", AtlasStringUtil.getOption(request.getOptions(), "size")); return getZipDirectEntityImportStream(request, inputStream); } @@ -294,6 +294,6 @@ public class ImportService { } private boolean isMigrationMode(AtlasImportRequest request) { - return request.getOptions().containsKey(AtlasImportRequest.OPTION_KEY_MIGRATION); + return AtlasStringUtil.hasOption(request.getOptions(), AtlasImportRequest.OPTION_KEY_MIGRATION); } } diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/BulkImporterImpl.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/BulkImporterImpl.java index 8e17fd410..0d3e911be 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/BulkImporterImpl.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/BulkImporterImpl.java @@ -36,6 +36,7 @@ import org.apache.atlas.repository.store.graph.v2.bulkimport.RegularImport; import org.apache.atlas.type.AtlasEntityType; import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.type.Constants; +import org.apache.atlas.utils.AtlasStringUtil; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,8 +67,7 @@ public class BulkImporterImpl implements BulkImporter { public EntityMutationResponse bulkImport(EntityImportStream entityStream, AtlasImportResult importResult) throws AtlasBaseException { ImportStrategy importStrategy = null; - if (importResult.getRequest().getOptions() != null && - importResult.getRequest().getOptions().containsKey(AtlasImportRequest.OPTION_KEY_MIGRATION)) { + if (AtlasStringUtil.hasOption(importResult.getRequest().getOptions(), AtlasImportRequest.OPTION_KEY_MIGRATION)) { importStrategy = new MigrationImport(this.atlasGraph, new AtlasGraphProvider(), this.typeRegistry); } else { importStrategy = new RegularImport(this.atlasGraph, this.entityStore, this.typeRegistry); diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/bulkimport/MigrationImport.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/bulkimport/MigrationImport.java index d6f23d6e2..f8c9218c6 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/bulkimport/MigrationImport.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/bulkimport/MigrationImport.java @@ -39,6 +39,7 @@ import org.apache.atlas.repository.store.graph.v2.IAtlasEntityChangeNotifier; import org.apache.atlas.repository.store.graph.v2.bulkimport.pc.EntityConsumerBuilder; import org.apache.atlas.repository.store.graph.v2.bulkimport.pc.EntityCreationManager; import org.apache.atlas.type.AtlasTypeRegistry; +import org.apache.atlas.utils.AtlasStringUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -89,7 +90,7 @@ public class MigrationImport extends ImportStrategy { private DataMigrationStatusService createMigrationStatusService(AtlasImportResult importResult) { DataMigrationStatusService dataMigrationStatusService = new DataMigrationStatusService(); - dataMigrationStatusService.init(importResult.getRequest().getOptions().get(AtlasImportRequest.OPTION_KEY_MIGRATION_FILE_NAME)); + dataMigrationStatusService.init(AtlasStringUtil.getOption(importResult.getRequest().getOptions(), AtlasImportRequest.OPTION_KEY_MIGRATION_FILE_NAME)); return dataMigrationStatusService; }