Commit e92502dd by ashutoshm Committed by Madhan Neethiraj

ATLAS-1434: Updated typename validation to allow "." for classifications

parent d8db4310
...@@ -56,9 +56,13 @@ import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_MAP_SUF ...@@ -56,9 +56,13 @@ import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_MAP_SUF
*/ */
public class AtlasTypeUtil { public class AtlasTypeUtil {
private static final Set<String> ATLAS_BUILTIN_TYPENAMES = new HashSet<>(); private static final Set<String> ATLAS_BUILTIN_TYPENAMES = new HashSet<>();
private static final String NAME_REGEX = "[a-zA-z][a-zA-Z0-9_ ]*"; private static final String NAME_REGEX = "[a-zA-Z][a-zA-Z0-9_ ]*";
private static final String TRAIT_NAME_REGEX = "[a-zA-Z][a-zA-Z0-9_ .]*";
private static final Pattern NAME_PATTERN = Pattern.compile(NAME_REGEX); private static final Pattern NAME_PATTERN = Pattern.compile(NAME_REGEX);
private static final Pattern TRAIT_NAME_PATTERN = Pattern.compile(TRAIT_NAME_REGEX);
private static final String InvalidTypeNameErrorMessage = "Only characters, numbers and '_' are allowed in names.";
private static final String InvalidTraitTypeNameErrorMessage = "Only characters, numbers, '.' and '_' are allowed in names.";
static { static {
Collections.addAll(ATLAS_BUILTIN_TYPENAMES, AtlasBaseTypeDef.ATLAS_BUILTIN_TYPES); Collections.addAll(ATLAS_BUILTIN_TYPENAMES, AtlasBaseTypeDef.ATLAS_BUILTIN_TYPES);
...@@ -93,6 +97,20 @@ public class AtlasTypeUtil { ...@@ -93,6 +97,20 @@ public class AtlasTypeUtil {
return m.matches(); return m.matches();
} }
public static String getInvalidTypeNameErrorMessage() {
return InvalidTypeNameErrorMessage;
}
public static boolean isValidTraitTypeName(String typeName) {
Matcher m = TRAIT_NAME_PATTERN.matcher(typeName);
return m.matches();
}
public static String getInvalidTraitTypeNameErrorMessage() {
return InvalidTraitTypeNameErrorMessage;
}
public static void validateType(AtlasBaseTypeDef typeDef) throws AtlasBaseException { public static void validateType(AtlasBaseTypeDef typeDef) throws AtlasBaseException {
String typeName = typeDef.getName(); String typeName = typeDef.getName();
......
...@@ -71,6 +71,7 @@ import org.codehaus.jettison.json.JSONObject; ...@@ -71,6 +71,7 @@ import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
...@@ -88,6 +89,9 @@ import javax.inject.Singleton; ...@@ -88,6 +89,9 @@ import javax.inject.Singleton;
*/ */
@Singleton @Singleton
public class DefaultMetadataService implements MetadataService, ActiveStateChangeHandler, TypeDefChangeListener { public class DefaultMetadataService implements MetadataService, ActiveStateChangeHandler, TypeDefChangeListener {
private enum OperationType {
CREATE, UPDATE, DELETE
};
private static final Logger LOG = LoggerFactory.getLogger(DefaultMetadataService.class); private static final Logger LOG = LoggerFactory.getLogger(DefaultMetadataService.class);
private final short maxAuditResults; private final short maxAuditResults;
...@@ -177,12 +181,12 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang ...@@ -177,12 +181,12 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
*/ */
@Override @Override
public JSONObject createType(String typeDefinition) throws AtlasException { public JSONObject createType(String typeDefinition) throws AtlasException {
return createOrUpdateTypes(typeDefinition, false); return createOrUpdateTypes(OperationType.CREATE, typeDefinition, false);
} }
private JSONObject createOrUpdateTypes(String typeDefinition, boolean isUpdate) throws AtlasException { private JSONObject createOrUpdateTypes(OperationType opType, String typeDefinition, boolean isUpdate) throws AtlasException {
typeDefinition = ParamChecker.notEmpty(typeDefinition, "type definition"); typeDefinition = ParamChecker.notEmpty(typeDefinition, "type definition");
TypesDef typesDef = validateTypeDefinition(typeDefinition); TypesDef typesDef = validateTypeDefinition(opType, typeDefinition);
try { try {
...@@ -214,10 +218,12 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang ...@@ -214,10 +218,12 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
@Override @Override
public JSONObject updateType(String typeDefinition) throws AtlasException { public JSONObject updateType(String typeDefinition) throws AtlasException {
return createOrUpdateTypes(typeDefinition, true); return createOrUpdateTypes(OperationType.UPDATE, typeDefinition, true);
} }
private TypesDef validateTypeDefinition(String typeDefinition) throws AtlasException { private TypesDef validateTypeDefinition(OperationType opType, String typeDefinition) throws AtlasException {
final String exceptionErrorMessageFormat = "%s for '%s' failed: %s";
try { try {
TypesDef typesDef = TypesSerialization.fromJson(typeDefinition); TypesDef typesDef = TypesSerialization.fromJson(typeDefinition);
if (typesDef.isEmpty()) { if (typesDef.isEmpty()) {
...@@ -226,22 +232,26 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang ...@@ -226,22 +232,26 @@ public class DefaultMetadataService implements MetadataService, ActiveStateChang
for (HierarchicalTypeDefinition<ClassType> t : typesDef.classTypesAsJavaList()) { for (HierarchicalTypeDefinition<ClassType> t : typesDef.classTypesAsJavaList()) {
if (!AtlasTypeUtil.isValidTypeName(t.typeName)) if (!AtlasTypeUtil.isValidTypeName(t.typeName))
throw new AtlasException("Only characters, numbers and '_' are allowed in class names. " + t.toString()); throw new AtlasException(
String.format(exceptionErrorMessageFormat, opType.toString(), t.typeName, AtlasTypeUtil.getInvalidTypeNameErrorMessage()));
} }
for (StructTypeDefinition t : typesDef.structTypesAsJavaList()) { for (StructTypeDefinition t : typesDef.structTypesAsJavaList()) {
if (!AtlasTypeUtil.isValidTypeName(t.typeName)) if (!AtlasTypeUtil.isValidTypeName(t.typeName))
throw new AtlasException("Only characters, numbers and '_' are allowed in struct names. " + t.toString()); throw new AtlasException(
String.format(exceptionErrorMessageFormat, opType.toString(), t.typeName, AtlasTypeUtil.getInvalidTypeNameErrorMessage()));
} }
for (EnumTypeDefinition t : typesDef.enumTypesAsJavaList()) { for (EnumTypeDefinition t : typesDef.enumTypesAsJavaList()) {
if (!AtlasTypeUtil.isValidTypeName(t.name)) if (!AtlasTypeUtil.isValidTypeName(t.name))
throw new AtlasException("Only characters, numbers and '_' are allowed in enum names. " + t.toString()); throw new AtlasException(
String.format(exceptionErrorMessageFormat, opType.toString(), t.name, AtlasTypeUtil.getInvalidTypeNameErrorMessage()));
} }
for (HierarchicalTypeDefinition<TraitType> t : typesDef.traitTypesAsJavaList()) { for (HierarchicalTypeDefinition<TraitType> t : typesDef.traitTypesAsJavaList()) {
if (!AtlasTypeUtil.isValidTypeName(t.typeName)) if (!AtlasTypeUtil.isValidTraitTypeName(t.typeName))
throw new AtlasException("Only characters, numbers and '_' are allowed in trait names. " + t.toString()); throw new AtlasException(
String.format(exceptionErrorMessageFormat, opType.toString(), t.typeName, AtlasTypeUtil.getInvalidTraitTypeNameErrorMessage()));
} }
return typesDef; return typesDef;
......
...@@ -39,6 +39,7 @@ import org.apache.atlas.repository.audit.HBaseTestUtils; ...@@ -39,6 +39,7 @@ import org.apache.atlas.repository.audit.HBaseTestUtils;
import org.apache.atlas.repository.graph.AtlasGraphProvider; import org.apache.atlas.repository.graph.AtlasGraphProvider;
import org.apache.atlas.services.DefaultMetadataService; import org.apache.atlas.services.DefaultMetadataService;
import org.apache.atlas.services.MetadataService; import org.apache.atlas.services.MetadataService;
import org.apache.atlas.type.AtlasTypeUtil;
import org.apache.atlas.typesystem.IReferenceableInstance; import org.apache.atlas.typesystem.IReferenceableInstance;
import org.apache.atlas.typesystem.IStruct; import org.apache.atlas.typesystem.IStruct;
import org.apache.atlas.typesystem.ITypedReferenceableInstance; import org.apache.atlas.typesystem.ITypedReferenceableInstance;
...@@ -1146,7 +1147,7 @@ public class DefaultMetadataServiceTest { ...@@ -1146,7 +1147,7 @@ public class DefaultMetadataServiceTest {
@Test @Test
public void testTypeWithDotsCreationShouldNotBeCreated() throws AtlasException, JSONException { public void testTypeWithDotsCreationShouldNotBeCreated() throws AtlasException, JSONException {
String typeName = "test_.v1_type_"+ RandomStringUtils.randomAlphanumeric(10); String typeName = "test_.v1_type_XXXX";
HierarchicalTypeDefinition<ClassType> typeDef = TypesUtil.createClassTypeDef( HierarchicalTypeDefinition<ClassType> typeDef = TypesUtil.createClassTypeDef(
typeName, ImmutableSet.<String>of(), typeName, ImmutableSet.<String>of(),
TypesUtil.createUniqueRequiredAttrDef("test_type_attribute", DataTypes.STRING_TYPE)); TypesUtil.createUniqueRequiredAttrDef("test_type_attribute", DataTypes.STRING_TYPE));
...@@ -1156,7 +1157,7 @@ public class DefaultMetadataServiceTest { ...@@ -1156,7 +1157,7 @@ public class DefaultMetadataServiceTest {
metadataService.createType(TypesSerialization.toJson(typesDef)); metadataService.createType(TypesSerialization.toJson(typesDef));
fail("Expected IllegalArgumentException"); fail("Expected IllegalArgumentException");
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
//expected assertTrue (e.getCause().getMessage().contains(AtlasTypeUtil.getInvalidTypeNameErrorMessage()), e.getCause().getMessage());
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment