Skip to content

Commit

Permalink
[#8780] Add ContentLength Util
Browse files Browse the repository at this point in the history
  • Loading branch information
emeroad committed Apr 18, 2022
1 parent 2197e63 commit 514dd71
Show file tree
Hide file tree
Showing 2 changed files with 243 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package com.navercorp.pinpoint.common.util;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public class ContentLength {

public static final int SKIP = Integer.MIN_VALUE;
public static final int NOT_EXIST = -1;

private final LengthFunction[] functions;

public ContentLength(LengthFunction[] functions) {
this.functions = Objects.requireNonNull(functions, "functions");
}

public int getLength(Object content) {
long length = getLongLength(content);
return toInt(length);
}

private int toInt(long value) {
if (value > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}
return (int) value;
}

public long getLongLength(Object content) {
if (content == null) {
return NOT_EXIST;
}
for (LengthFunction function : functions) {
long length = function.getLength(content);
if (length == SKIP) {
continue;
}
return length;
}
return NOT_EXIST;
}


public static Builder newBuilder() {
return new Builder();
}

public static class Builder {
private static final Map<Class<?>, LengthFunction> MAPPING = getMapping();

private static Map<Class<?>, LengthFunction> getMapping() {
Map<Class<?>, LengthFunction> map = new LinkedHashMap<>();
map.put(String.class, new StringLength());
map.put(byte[].class, new PrimitiveByteArrayLength());
map.put(char[].class, new PrimitiveCharArrayLength());
map.put(File.class, new FileLength());
map.put(InputStream.class, new InputStreamAvailableLength());
return map;
}

private Builder() {
}

private final List<LengthFunction> list = new ArrayList<>();

public void addContentType(Class<?> content) {
Objects.requireNonNull(content, "content");
LengthFunction lengthFunction = MAPPING.get(content);
if (lengthFunction == null) {
throw new IllegalArgumentException("unsupported content :" + content);
}
list.add(lengthFunction);
}

public void addFunction(LengthFunction function) {
Objects.requireNonNull(function, "function");
list.add(function);
}

public ContentLength build() {
LengthFunction[] functions = list.toArray(new LengthFunction[0]);
return new ContentLength(functions);
}
}

public interface LengthFunction {
long getLength(Object context);
}

public static class PrimitiveByteArrayLength implements LengthFunction {
public long getLength(Object context) {
if (context instanceof byte[]) {
return ((byte[]) context).length;
}
return SKIP;
}


}

public static class PrimitiveCharArrayLength implements LengthFunction {
public long getLength(Object context) {
if (context instanceof char[]) {
return ((char[]) context).length;
}
return SKIP;
}

}

public static class StringLength implements LengthFunction {
public long getLength(Object context) {
if (context instanceof String) {
return ((String) context).length();
}
return SKIP;
}

}

public static class FileLength implements LengthFunction {
public long getLength(Object context) {
if (context instanceof File) {
return ((File) context).length();
}
return SKIP;
}
}

public static class InputStreamAvailableLength implements LengthFunction {
public long getLength(Object context) {
if (context instanceof InputStream) {
try {
return ((InputStream) context).available();
} catch (IOException ignore) {
// io error
return NOT_EXIST;
}
}
return SKIP;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.navercorp.pinpoint.common.util;

import org.junit.Test;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import static org.mockito.Mockito.*;
import static org.mockito.Mockito.when;

public class ContentLengthTest {

@Test
public void length() throws IOException {
ContentLength.Builder builder = ContentLength.newBuilder();
builder.addContentType(String.class);
builder.addContentType(byte[].class);
builder.addContentType(char[].class);
builder.addContentType(InputStream.class);
builder.addContentType(File.class);
ContentLength contentLength = builder.build();

String strContent = "abc";
int strLength = contentLength.getLength(strContent);
org.junit.Assert.assertEquals(strContent.length(), strLength);

byte[] byteArray = new byte[1];
int bytesLength = contentLength.getLength(byteArray);
org.junit.Assert.assertEquals(byteArray.length, bytesLength);

char[] charArray = new char[5];
int charsLength = contentLength.getLength(charArray);
org.junit.Assert.assertEquals(charArray.length, charsLength);

InputStream inputStream = mock(InputStream.class);
when(inputStream.available()).thenReturn(20);
int streamLength = contentLength.getLength(inputStream);
org.junit.Assert.assertEquals(inputStream.available(), streamLength);

File file = mock(File.class);
when(file.length()).thenReturn(30L);
int fileLength = contentLength.getLength(file);
org.junit.Assert.assertEquals(file.length(), fileLength);
}

@Test
public void length_function() {
ContentLength.Builder builder = ContentLength.newBuilder();
builder.addFunction(new ContentLength.LengthFunction() {
@Override
public long getLength(Object context) {
if (context instanceof long[]) {
return ((long[]) context).length;
}
return ContentLength.SKIP;
}
});

ContentLength contentLength = builder.build();

int length = contentLength.getLength(new long[10]);
org.junit.Assert.assertEquals(10, length);
}

@Test
public void length_unknownType() {
ContentLength.Builder builder = ContentLength.newBuilder();
ContentLength contentLength = builder.build();

int length = contentLength.getLength("abc");
org.junit.Assert.assertEquals(ContentLength.NOT_EXIST, length);

int nullLength = contentLength.getLength(null);
org.junit.Assert.assertEquals(ContentLength.NOT_EXIST, nullLength);
}


@Test
public void overflow_file() {
ContentLength.Builder builder = ContentLength.newBuilder();
builder.addContentType(File.class);
ContentLength content = builder.build();

File file = mock(File.class);
when(file.length()).thenReturn(Long.MAX_VALUE);

int intLength = content.getLength(file);
org.junit.Assert.assertEquals(Integer.MAX_VALUE, intLength);

long longLength = content.getLongLength(file);
org.junit.Assert.assertEquals(Long.MAX_VALUE, longLength);
}
}

0 comments on commit 514dd71

Please sign in to comment.