0

Suppose I am passed an OutputStream variable. Is there any way to detect if the source of the OutputStream is an open file, or open socket etc?

If it is not possible, is it better if I know the variable is of type FileOutputStream, and hence I can get its FileDescriptor. Thank you.


UPDATE:

Each FileOutputStream instance has a FileDescriptor. I couldn't distinguish its source because from the Java document:

Instances of the file descriptor class serve as an opaque handle to the underlying machine-specific structure representing an open file, an open socket, or another source or sink of bytes. The main practical use for a file descriptor is to create a FileInputStream or FileOutputStream to contain it.


UPDATE2:

I'm developing an automated tool, built on top of a customized JVM, to analyze Java bytecode, and determine how many bytes the program writes to a file or sends over the socket, etc (in very simple programs). File, Socket etc are then processed differently.

The customized JVM lets me know when it executes the bytecode instruction INVOKEVIRTUAL, and I can check that the callee is of OutputStream. Now what I need to do is to determine where this OutputStream writes to File/Socket etc.

sean
  • 1,632
  • 2
  • 15
  • 34
  • 1
    I think you might be down the wrong track. What is it you really want to know? Whether it's a file stream, a network stream, or a memory stream (byte or string)? What the file name is? The URL source? The memory buffer? What? – Andreas Sep 20 '15 at 06:16
  • If you think I'm stupid, just say it. I don't mind. But do not vote to close without explaining. Thanks. – sean Sep 20 '15 at 06:30
  • Where did I ever say anything like that? I was asking for clarification of what your goal was, in order better help. – Andreas Sep 20 '15 at 06:35
  • @Andreas: I'm sorry, my previous comment is not for you. I'm asking the two people who voted to close without explaining. – sean Sep 20 '15 at 06:37
  • 1
    One of the confusion points is your first statement "source of the OutputStream". From your update2, it would appear you're looking for the *target* of the output stream, i.e. where are the bytes going, not where are they coming from. – Andreas Sep 20 '15 at 06:42
  • @Andreas: Yes, I mean the target. – sean Sep 20 '15 at 06:45

3 Answers3

3

Thinking simply, you can use instance of

if(myStream instanceof FileOutputStream){
    //this is FileOutputStream
}

But there are some situation that you cannot detect, example if that FileOutputStream is wrapped by an other OutputStream (like FilterOutputStream). So, if the instance of your stream is FilterOutputStream, you have to find the real one inner. When a stream is wrapped:

 public FilterOutputStream(OutputStream out) {
        this.out = out;
 }

But, by normal way, we cannot get this.out (protected) out to run instance of again. I think about reflection to get a protected or private field (Java reflection - access protected field)

And BUT again, if the inner stream is another FilterOutputStream again!!! you have to use a recursive function to detect.

Imagine Stream in Java like Matroska puppet!

This is just my idea. If you want to fully control it. You have to see the tree of Java IO

enter image description here

Community
  • 1
  • 1
yelliver
  • 5,648
  • 5
  • 34
  • 65
  • @yelliver: please see my update to the question. Since I have a customized JVM that allows me to capture the "write" method, so wrapping is not a problem for me at all. – sean Sep 20 '15 at 06:34
0

Since you're basically putting breakpoints on all calls to write, you need to examine the actual class for the method call:

  • If it's a FilterOutputStream (one of it's subclasses), ignore it. The write method of the wrapped stream will be called too.
  • If it's java.net.SocketOutputStream (not public, subclass of FileOutputStream), you know the target is a socket.
  • If it's FileOutputStream (not a subclass), the private field path has the file path used to open the stream.
  • If it's a ByteArrayOutputStream, you know the target is a memory buffer.
  • If it's something else, you'd need to research how to handle it, or just ignore.
Andreas
  • 154,647
  • 11
  • 152
  • 247
-1

use instanceof operator what type of object it is. For eaxmple you can check

if(currentObject instanceof FileOutputStream){}

or you can use

yourObject.getClass().getName()

user2864740
  • 60,010
  • 15
  • 145
  • 220
M Sach
  • 33,416
  • 76
  • 221
  • 314
  • Could you elaborate your answer please? I know `isntaceof`, but how to check if the source of an OutputStream is, e.g. an open socket, but not a file? – sean Sep 20 '15 at 06:03
  • If you have no clue what the source of your output COULD be, then you have no chance. But you can check against various possibilities and see, what it is. Of course, you might be out of luck of the original class does not have a getter for the source name, was transformed into a ByteArrayOutputStream, etc. Perhaps it might be a good idea to tell us, what you actually NEED that for? – Florian Schaetz Sep 20 '15 at 06:05
  • @MSach FileOutputStream can be used for either File or Socket. – sean Sep 20 '15 at 06:08
  • Seriously, how did *two* answers use the *invalid* `instance of` construct? – user2864740 Sep 20 '15 at 06:13
  • @FlorianSchaetz: Suppose I can capture the `write` instruction of OutputStream. I need to know if it writes to a file or write to a socket etc. – sean Sep 20 '15 at 06:18
  • 1
    @user2864740 Define "invalid"? It's not a good practice, obviously, but why "invalid"? – Florian Schaetz Sep 20 '15 at 07:02
  • @FlorianSchaetz I corrected *both* answers which used `instance of` in the code - hence being "invalid" - and when talking about the operator outside of code. – user2864740 Sep 20 '15 at 08:05