HBASE-21732 Should call toUpperCase before using Enum.valueOf in some methods for ColumnFamilyDescriptor

Signed-off-by: Zheng Hu <openinx@gmail.com>
This commit is contained in:
Duo Zhang 2019-01-16 18:38:58 +08:00 committed by zhangduo
parent 51c58e083c
commit 348cbf63ec
2 changed files with 119 additions and 15 deletions

View File

@ -17,7 +17,6 @@
*/
package org.apache.hadoop.hbase.client;
import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
@ -25,21 +24,23 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import org.apache.hadoop.hbase.HConstants;
import org.apache.hadoop.hbase.KeepDeletedCells;
import org.apache.hadoop.hbase.MemoryCompactionPolicy;
import org.apache.yetus.audience.InterfaceAudience;
import org.apache.hadoop.hbase.exceptions.DeserializationException;
import org.apache.hadoop.hbase.exceptions.HBaseException;
import org.apache.hadoop.hbase.io.compress.Compression;
import org.apache.hadoop.hbase.io.encoding.DataBlockEncoding;
import org.apache.hadoop.hbase.regionserver.BloomType;
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ColumnFamilySchema;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.hbase.util.PrettyPrinter;
import org.apache.hadoop.hbase.util.PrettyPrinter.Unit;
import org.apache.yetus.audience.InterfaceAudience;
import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;
import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;
import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.ColumnFamilySchema;
/**
* @since 2.0.0
@ -129,7 +130,6 @@ public class ColumnFamilyDescriptorBuilder {
private static final Bytes BLOOMFILTER_BYTES = new Bytes(Bytes.toBytes(BLOOMFILTER));
@InterfaceAudience.Private
public static final String REPLICATION_SCOPE = "REPLICATION_SCOPE";
private static final Bytes REPLICATION_SCOPE_BYTES = new Bytes(Bytes.toBytes(REPLICATION_SCOPE));
@InterfaceAudience.Private
public static final String MAX_VERSIONS = HConstants.VERSIONS;
private static final Bytes MAX_VERSIONS_BYTES = new Bytes(Bytes.toBytes(MAX_VERSIONS));
@ -778,8 +778,7 @@ public class ColumnFamilyDescriptorBuilder {
@Override
public Compression.Algorithm getCompressionType() {
return getStringOrDefault(COMPRESSION_BYTES,
Compression.Algorithm::valueOf,
DEFAULT_COMPRESSION);
n -> Compression.Algorithm.valueOf(n.toUpperCase()), DEFAULT_COMPRESSION);
}
/**
@ -799,8 +798,7 @@ public class ColumnFamilyDescriptorBuilder {
@Override
public DataBlockEncoding getDataBlockEncoding() {
return getStringOrDefault(DATA_BLOCK_ENCODING_BYTES,
DataBlockEncoding::valueOf,
DataBlockEncoding.NONE);
n -> DataBlockEncoding.valueOf(n.toUpperCase()), DataBlockEncoding.NONE);
}
/**
@ -833,8 +831,7 @@ public class ColumnFamilyDescriptorBuilder {
@Override
public Compression.Algorithm getCompactionCompressionType() {
return getStringOrDefault(COMPRESSION_COMPACT_BYTES,
Compression.Algorithm::valueOf,
getCompressionType());
n -> Compression.Algorithm.valueOf(n.toUpperCase()), getCompressionType());
}
/**
@ -868,7 +865,8 @@ public class ColumnFamilyDescriptorBuilder {
@Override
public MemoryCompactionPolicy getInMemoryCompaction() {
return getStringOrDefault(IN_MEMORY_COMPACTION_BYTES, MemoryCompactionPolicy::valueOf, null);
return getStringOrDefault(IN_MEMORY_COMPACTION_BYTES,
n -> MemoryCompactionPolicy.valueOf(n.toUpperCase()), null);
}
/**
@ -962,7 +960,8 @@ public class ColumnFamilyDescriptorBuilder {
@Override
public BloomType getBloomFilterType() {
return getStringOrDefault(BLOOMFILTER_BYTES, BloomType::valueOf, DEFAULT_BLOOMFILTER);
return getStringOrDefault(BLOOMFILTER_BYTES, n -> BloomType.valueOf(n.toUpperCase()),
DEFAULT_BLOOMFILTER);
}
public ModifyableColumnFamilyDescriptor setBloomFilterType(final BloomType bt) {
@ -1302,7 +1301,8 @@ public class ColumnFamilyDescriptorBuilder {
@Override
public MobCompactPartitionPolicy getMobCompactPartitionPolicy() {
return getStringOrDefault(MOB_COMPACT_PARTITION_POLICY_BYTES,
MobCompactPartitionPolicy::valueOf, DEFAULT_MOB_COMPACT_PARTITION_POLICY);
n -> MobCompactPartitionPolicy.valueOf(n.toUpperCase()),
DEFAULT_MOB_COMPACT_PARTITION_POLICY);
}
/**

View File

@ -0,0 +1,104 @@
/**
* 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.hadoop.hbase.client;
import static org.junit.Assert.assertEquals;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.NoSuchElementException;
import org.apache.hadoop.hbase.HBaseClassTestRule;
import org.apache.hadoop.hbase.testclassification.ClientTests;
import org.apache.hadoop.hbase.testclassification.SmallTests;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.experimental.categories.Category;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Testcase for HBASE-21732. Make sure that all enum configurations can accept lower case value.
*/
@Category({ ClientTests.class, SmallTests.class })
public class TestColumnFamilyDescriptorLowerCaseEnum {
@ClassRule
public static final HBaseClassTestRule CLASS_RULE =
HBaseClassTestRule.forClass(TestColumnFamilyDescriptorLowerCaseEnum.class);
private static final Logger LOG =
LoggerFactory.getLogger(TestColumnFamilyDescriptorLowerCaseEnum.class);
private Method getSetMethod(Method getMethod, Class<?> enumType) throws NoSuchMethodException {
String methodName = getMethod.getName().replaceFirst("get", "set");
return ColumnFamilyDescriptorBuilder.class.getMethod(methodName, enumType);
}
private Enum<?> getEnumValue(Class<?> enumType) {
for (Enum<?> enumConst : enumType.asSubclass(Enum.class).getEnumConstants()) {
if (!enumConst.name().equalsIgnoreCase("NONE") && !enumConst.name().equals("DEFAULT")) {
return enumConst;
}
}
throw new NoSuchElementException(enumType.getName());
}
private boolean contains(Collection<Enum<?>> enumConsts, String value) {
return enumConsts.stream().anyMatch(e -> e.name().equals(value));
}
@Test
public void test()
throws IllegalAccessException, InvocationTargetException, NoSuchMethodException {
Map<Method, Enum<?>> getMethod2Value = new HashMap<>();
ColumnFamilyDescriptorBuilder builder =
ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("test"));
for (Method method : ColumnFamilyDescriptor.class.getMethods()) {
if (method.getParameterCount() == 0 && method.getReturnType().isEnum()) {
LOG.info("Checking " + method);
Class<?> enumType = method.getReturnType();
Method setMethod = getSetMethod(method, enumType);
Enum<?> enumConst = getEnumValue(enumType);
LOG.info("Using " + setMethod + " to set the value to " + enumConst);
setMethod.invoke(builder, enumConst);
getMethod2Value.put(method, enumConst);
}
}
ColumnFamilyDescriptor desc = builder.build();
ColumnFamilyDescriptorBuilder builder2 =
ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes("test2"));
desc.getValues().forEach((k, v) -> {
LOG.info(k.toString() + "=>" + v.toString());
String str = Bytes.toString(v.get(), v.getOffset(), v.getLength());
if (contains(getMethod2Value.values(), str)) {
LOG.info("Set to lower case " + str.toLowerCase());
builder2.setValue(k, new Bytes(Bytes.toBytes(str.toLowerCase())));
}
});
ColumnFamilyDescriptor desc2 = builder2.build();
for (Map.Entry<Method, Enum<?>> entry : getMethod2Value.entrySet()) {
assertEquals(entry.getKey() + " should return " + entry.getValue(), entry.getValue(),
entry.getKey().invoke(desc2));
}
}
}