1

I have a class that takes an InputStream as an argument to read data.

public Foo {
  private DataInput in;

  public Foo(InputStream ism) {
    in = new DataInputStream(ism);
  }

  public byte readByte() throws IOException {
    return in.readByte();
  }
}

Sometimes this InputStream might come from a Socket, e.g.,

ism = new BufferedInputStream(sock.getInputStream());
foo = new Foo(ism);

My question is, is it possible to check from within Foo that the input stream comes from Socket, i.e., it's a network I/O rather than local I/O? Since the

socket.getInputStream

call returns the abstract class. I don't know which concrete input stream implementation to test for.

Edit: the motivation is that there is a piece of big Java software that has this structure. Foo is created in many places. Some place with file input stream while others with socket input stream. The software can perform poorly when the read is across the network. So I want to see if it's possible do tracing to differentiate the two scenarios for this software without changing much of its code. I'm using AspectJ to write the tracing in the hope to not create much mess to this existing software.

6
  • 2
    No (at least not without an ugly reflection-based solution), since you're wrapping it into a BufferedInputStream. But you shouldn't have to care: an InputStream is an InputStream is an InputStream. What are you trying to achieve? Commented Jun 30, 2017 at 6:25
  • 1
    No, you've written the entire interface of Foo to be independent of and isolated from sockets. If you want Foo to know about sockets, you'd have to give it a socket. Commented Jun 30, 2017 at 6:27
  • I need to do some tracing to differentiate when Foo is doing network read instead of local File read. Commented Jun 30, 2017 at 6:27
  • try System.out.println(in.getClass().getName()) , and it will surely indicate if your InputStream is coming from a file or socket. For InputStream coming from Sockets, in.getClass().getName() will surely return a different result Commented Jun 30, 2017 at 6:37
  • If you can only modify Foo, then there is no pretty solution. Can you modify the classes that use Foo, or are they too numerous? Commented Jun 30, 2017 at 6:48

2 Answers 2

1

The problem is that an InputStream can be a FilterInputStream that is constructed around another InputStream and that socket just returns an InputStream.

One approach, very dirt & buggy: find the root InputStream, that is, recursively/loop if it is an instance of FilterInputStream, check its parent InputStream (protected field in). Then check the class of the root, the name probably contains "Socket" if it comes from a Socket.

AspectJ idea (I do not have that much experience with it): you should be able to add an aspect to the getInputStream method of Socket that stores the returned InputStream in a list (or similar) for later checking, or somehow marks that InputStream (adding a flag/method to it?).

Sign up to request clarification or add additional context in comments.

Comments

0

You can create 2 superclasses of input stream before passing it into Foo class.

NetworkInputStream nis = new NetworkInputStream(sock.getInputStream());
Foo networkFoo = new Foo(nis);

FileInputStream fis = new FileInputStream(file.getInputStream());
Foo fileFoo = new Foo(fis);


public class NetworkInputStream extends BufferedInputStream {}

public class FileInputStream extends BufferedInputStream {}

Then, on Foo class:

public Foo(InputStream ism) {
    if (ism instanceof NetworkInputStream) {
        //Do whatever if it's from network stream 
    }
    if (ism instanceof FileInputStream) {
       //Do whateverelse
    }
    in = new DataInputStream(ism);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.