ABOUT ME

IT 블로그

Today
Yesterday
Total
  • [Java9] IO
    Java/기본 2018. 5. 14. 00:19
    728x90
    반응형

    InputStream

    • java.io.InputStream
    • 읽기/복사에 관한 3개의 메소드 추가됨
      • readAllBytes() : intput stream의 모든 바이트들을 읽음
      • readNBytes(byte[] b, int off, int len) : b배열의 off위치부터 len byte만큼 읽음
      • transferTo(OutputStream out) : input stream에서 모든 bytes를 읽고, OutputStream에 씀
    • 이제 Apache Commons IO 같은거 안써도 됨
    package java9.book;
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Test;
    import java.io.ByteArrayOutputStream;
    import java.io.InputStream;
    import static org.junit.jupiter.api.Assertions.assertEquals;
    public class TestInputStream {
    private InputStream inputStream;
    private static final String CONTENT = "Hello World";
    @BeforeEach
    public void setUp() {
    this.inputStream = TestInputStream.class.getResourceAsStream("input.txt");
    }
    @Test
    public void testReadAllBytes() throws Exception {
    final String content = new String(this.inputStream.readAllBytes());
    assertEquals(CONTENT, content);
    }
    @Test
    public void testReadNBytes() throws Exception {
    final byte[] data = new byte[5];
    this.inputStream.readNBytes(data, 0, 5);
    assertEquals("Hello", new String(data));
    }
    @Test
    public void testTransferTo() throws Exception {
    final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
    this.inputStream.transferTo(outputStream);
    assertEquals(CONTENT, outputStream.toString());
    }
    }
    // Exploring Java 9, p.134


    The ObjectInputStream Filter

    • 객체를 저장하거나 네트워크 전송을 위해 직렬화 함
    • 데이터를 객체로 역직렬화 할 때 데이터가 유효한지 검증이 필요함
    • 이제 입력을 필터링하기 위해 java.io.ObjectInputStream에 새로운 함수형인터페이스인 java.io.ObjectInputFilter를 사용할 수 있음
    • ObjectInputFilter에는 Status checkInput(FilterInfo filterInfo); 메소드가 있음
    • ObjectInputFilter.FilterInfo에는 역직렬화되는 객체와 ObjectInputStream객체의 통계 정보가 포함 (아래 표1.1)

    표 1.1 ObjectInputFilter.FilterInfo의 메소드

     메소드

     설명

     Class<?> serialClass()

     역직렬화 되지 않은 객체의 클래스를 반환

     long arrayLength()

     역직렬화 된 객체가 배열이면, 배열의 길이를 반환 (그렇지 않으면 -1반환)

     long depth()

     객체 그래프에서 현재 객체의 깊이를 반환

     long references()

     현재 참조객체의 수를 반환

     long streamBytes()

     현재 소비된 bytes의 수를 반환 


    표 1.2 ObjectInputFilter.Status

     Status

     설명

     ALLOWED

     역직렬화 허용

     REJECTED

     역직렬화 거부

     UNDECIDED

     필터가 역직렬화 허용/거부 정하지 못함

    • ObjectInputFilter에서 상태를 REJECTED 설정 해두면 ObjectInputStream가 java.io.InvalidClassException를 발생(throw)시킴
    • setObjectInputFilter() 메소드를 이용하여 필터 설정
    • setSerialFilter
      • static 메소드인 setSerialFilter를 설정할 수 있음. 개별 필터가 설정 안되어 있으면 사용됨
      • String 패턴을 이용하여 작성하기 쉬움
      • 세미콜론(;)을 이용하여 여러개의 패턴 작성 가능



    package java9.book;
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Disabled;
    import org.junit.jupiter.api.Test;
    import java.io.*;
    import static org.junit.jupiter.api.Assertions.assertEquals;
    import static org.junit.jupiter.api.Assertions.assertThrows;
    public class TestObjectInputFilter {
    static class A implements Serializable {
    public int a = 1;
    public B b = new B();
    }
    static class B implements Serializable {
    public String b = "hello";
    public C c = new C();
    }
    static class C implements Serializable {
    public int c = 2;
    public D[] ds = new D[]{new D(), new D()};
    }
    static class D implements Serializable {
    public String d = "world";
    }
    private ByteArrayInputStream objectInput;
    @BeforeEach
    public void setUp() throws Exception {
    final A a = new A();
    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    final ObjectOutputStream outputStream = new ObjectOutputStream(baos);
    outputStream.writeObject(a);
    this.objectInput = new ByteArrayInputStream(baos.toByteArray());
    }
    @Test
    public void testFilterByClass() throws Exception {
    final ObjectInputStream inputStream = new ObjectInputStream(this.objectInput);
    inputStream.setObjectInputFilter(filterInfo -> {
    if (B.class.isAssignableFrom(filterInfo.serialClass())) {
    return ObjectInputFilter.Status.REJECTED;
    }
    return ObjectInputFilter.Status.UNDECIDED;
    });
    assertThrows(InvalidClassException.class, () -> {
    final A a = (A) inputStream.readObject();
    assertEquals(1, a.a);
    });
    }
    @Test
    public void testFilterByDepth() throws Exception {
    final ObjectInputStream inputStream = new ObjectInputStream(this.objectInput);
    inputStream.setObjectInputFilter(filterInfo -> {
    if (filterInfo.depth() > 6) {
    return ObjectInputFilter.Status.REJECTED;
    }
    return ObjectInputFilter.Status.UNDECIDED;
    });
    final A a = (A) inputStream.readObject();
    assertEquals(1, a.a);
    }
    @Test
    public void testProcessWideFilter() throws Exception {
    ObjectInputFilter.Config.setSerialFilter(filterInfo -> {
    if (C.class.isAssignableFrom(filterInfo.serialClass())) {
    return ObjectInputFilter.Status.REJECTED;
    }
    return ObjectInputFilter.Status.UNDECIDED;
    });
    final ObjectInputStream inputStream = new ObjectInputStream(this.objectInput);
    assertThrows(InvalidClassException.class, () -> {
    final A a = (A) inputStream.readObject();
    assertEquals(1, a.a);
    });
    }
    @Test
    @Disabled
    public void testFilterPattern() throws Exception {
    ObjectInputFilter.Config.setSerialFilter(
    ObjectInputFilter.Config.createFilter("!java9.book.**"));
    final ObjectInputStream inputStream = new ObjectInputStream(this.objectInput);
    assertThrows(InvalidClassException.class, () -> {
    final A a = (A) inputStream.readObject();
    assertEquals(1, a.a);
    });
    }
    }
    // Exploring Java 9, p.137

    출처


    반응형

    댓글

Designed by Tistory.