-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
243 additions
and
0 deletions.
There are no files selected for viewing
149 changes: 149 additions & 0 deletions
149
commons/src/main/java/com/navercorp/pinpoint/common/util/ContentLength.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} | ||
} |
94 changes: 94 additions & 0 deletions
94
commons/src/test/java/com/navercorp/pinpoint/common/util/ContentLengthTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |