Check if Java InputStream comes from Socket - java

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.

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?).

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);
}

Related

designing classes for other developers to use in java

class CSVReader {
private List<String> output;
private InputStream input;
public CSVReader(InputStream input) {
this.input = input;
}
public void read() throws Exception{
//do something with the inputstream
// create output list.
}
public List<String> getOutput() {
return Collections.unmodifiableList(output);
}
I am trying to create a simple class which will be part of a library. I would like to create code that satisfies the following conditions:
handles all potential errors or wraps them into library errors and
throws them.
creates meaningful and complete object states (no incomplete object structures).
easy to utilize by developers using the library
Now, when I evaluated the code above, against the goals, I realized that I failed badly. A developer using this code would have to write something like this -
CSVReader reader = new CVSReader(new FileInputStream("test.csv");
reader.read();
read.getOutput();
I see the following issues straight away -
- developer has to call read first before getOutput. There is no way for him to know this intuitively and this is probably bad design.
So, I decided to fix the code and write something like this
public List<String> getOutput() throws IOException{
if(output==null)
read();
return Collections.unmodifiableList(output);
}
OR this
public List<String> getOutput() {
if(output==null)
throw new IncompleteStateException("invoke read before getoutput()");
return Collections.unmodifiableList(output);
}
OR this
public CSVReader(InputStream input) {
read(); //throw runtime exception
}
OR this
public List<String> read() throws IOException {
//read and create output list.
// return list
}
What is a good way to achieve my goals? Should the object state be always well defined? - there is never a state where "output" is not defined, so I should create the output as part of constructor? Or should the class ensure that a created instance is always valid, by calling "read" whenever it finds that "output" is not defined and just throw a runtime exception? What is a good approach/ best practice here?
I would make read() private and have getOutput() call it as an implementation detail. If the point of exposing read() is to lazy-load the file, you can do that with exposing getOutput only
public List<String> getOutput() {
if (output == null) {
try {
output = read();
} catch (IOException) {
//here you either wrap into your own exception and then declare it in the signature of getOutput, or just not catch it and make getOutput `throws IOException`
}
}
return Collections.unmodifiableList(output);
}
The advantage of this is that the interface of your class is very trivial: you give me an input (via constructor) I give you an output (via getOutput), no magic order of calls while preserving lazy-loading which is nice if the file is big.
Another advantage of removing read from the public API is that you can go from lazy-loading to eager-loading and viceversa without affecting your clients. If you expose read you have to account for it being called in all possible states of your object (before it's loaded, while it's already running, after it already loaded). In short, always expose the least possible
So to address your specific questions:
Yes, the object state should always be well-defined. Your point of not knowing that an external call on read by the client class is needed is indeed a design smell
Yes, you could call read in the constructor and eagerly load everything upfront. Deciding to lazy-load or not is an implementation detail dependent on your context, it should not matter to a client of your class
Throwing an exception if read has not been called puts again the burden to calling things in the right, implicit order on the client, which is unnecessary due to your comment that output is never really undefined so the implementation itself can make the risk-free decision of when to call read
I would suggest you make your class as small as possible, dropping the getOutput() method all together.
The idea is to have a class that reads a CSV file and returns a list, representing the result. To achieve this, you can expose a single read() method, that will return a List<String>.
Something like:
public class CSVReader {
private final InputStream input;
public CSVReader(String filename) {
this.input = new FileInputStream(filename);
}
public List<String> read() {
// perform the actual reading here
}
}
You have a well defined class, a small interface to maintain and the instances of CSVReader are immutable.
Have getOutput check if it is null (or out of date) and load it in automatically if it is. This allows for a user of your class to not have to care about internal state of the class's file management.
However, you may also want to expose a read function so that the user can chose to load in the file when it is convenient. If you make the class for a concurrent environment, I would recommend doing so.
The first approach takes away some flexibility from the API: before the change the user could call read() in a context where an exception is expected, and then call getOutput() exception-free as many times as he pleases. Your change forces the user to catch a checked exception in contexts where it wasn't necessary before.
The second approach is how it should have been done in the first place: since calling read() is a prerequisite of calling getOutput(), it is a responsibility of your class to "catch" your users when they "forget" to make a call to read().
The third approach hides IOException, which may be a legitimate exception to catch. There is no way to let the user know if the exception is going to be thrown or not, which is a bad practice when designing runtime exceptions.
The root cause of your problem is that the class has two orthogonal responsibilities:
Reading a CSV, and
Storing the result of a read for later use.
If you separate these two responsibilities from each other, you would end up with a cleaner design, in which the users would have no confusion over what they must call, and in what order:
interface CSVData {
List<String> getOutput();
}
class CSVReader {
public static CSVData read(InputStream input) throws IOException {
...
}
}
You could combine the two into a single class with a factory method:
class CSVData {
private CSVData() { // No user instantiation
}
// Getting data is exception-free
public List<String> getOutput() {
...
}
// Creating instances requires a factory call
public static CSVData read(InputStream input) throws IOException {
...
}
}

How to unit test serialization with invariant checking?

I have an immutable class with invariant checking. According to Effective Java 2nd Ed item 76 it has a readObjects method that throws an InvalidObjectException if the deserialized object violates the invariants:
// readObject method with validity checking
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
// Check that our invariants are satisfied
if (/* some condition*/)
throw new InvalidObjectException("Invariant violated");
}
I know how to test serialization and deserialization, but this tests only the happy path. There is an ugly way of triggering the InvalidObjectException, where you hardcode a tampered byte stream (shamelessly stolen from EJ2 item 76):
public class BogusPeriod {
// manipulated byte stream
private static final byte[] serializedForm = new byte[] {
(byte)0xac, (byte)0xed, 0x00, 0x05, /* ca. 100 more bytes omitted */ };
// Returns the object with the specified serialized form
private static Object deserializeBogusPeriod() {
try {
InputStream is = new ByteArrayInputStream(serializedForm);
ObjectInputStream ois = new ObjectInputStream(is);
return ois.readObject();
} catch (Exception e) {
throw new IllegalArgumentException(e);
}
}
}
This is really ugly and will probably break as soon as the serializable class changes.
I wonder if there is a simpler method of creating test cases like that? Maybe there is a library that knows at which offsets of a byte stream specific values are located to allow tampering at run time?
You assume, that the object/class is deserializable from java (non corrupt data) and want to do some checks afterwards (like if a date in a string is formatted correct).
Writing your unit test for this, you could use a library like Serialysis (https://weblogs.java.net/blog/2007/06/12/disassembling-serialized-java-objects) to check generated byte streams by rightful streamed objects, find out where in the byte stream your data is located and modify your data during test setup.
THOUGH
IF you trust the source of your data you receive and have been able to deserialize, better use some kind of interceptor / validator provided by your framework of choice (Spring in SE, Java EE etc.) at the moment the object reaches your application.

Effect on the original InputStream after wrapping with BufferedInputStream

Suppose I have a method that take in an InputStream.
This method need to wrap this InputStream with a BufferedInputStream to use its mark and reset functionality. However, the passed in InputStream might still be used by the caller of the method.
public static void foo(InputStream is) throws Exception {
BufferedInputStream bis = new BufferedInputStream(is);
int b = bis.read();
}
public static void main(String[] args) {
try {
InputStream is = new FileInputStream(someFile);
foo(is);
int b = is.read(); // return -1
}catch (Exception e) {
e.printStackTrace();
}
}
My questions is: what exactly happen to the original InputStream when the BufferedInputStream is read (or initialized)?
My assumption is that the original InputStream will also move forward if the BufferedInputStream is read. However, after debugging my code, I have found that the InputStream will return -1 instead when read.
If the original InputStream is not readable after such process, how should I go about achieving my purpose:
InputStream is;
foo(is); // Method only take in generic InputStream object
// Processing of the passed in InputStream object require mark and reset functionality
int b = is.read(); // Return the next byte after the last byte that is read by foo()
EDIT:
I suppose what I'm asking for is quite generic and therefore requires a lot of work. As for what I'm working on, I actually don't need the full mark & reset capability so I have found a small work around. However, I will leave the 2nd part of the question here, so feel free to attempt this problem :).
The default bufferSize of a BufferedInputStream is 8192, so when you're reading from BufferedInputStream, it tries to fill it's buffer. So, if you have to read from your InputStream less bytes, than the bufferSize, then the full content of your InputStream is read to the buffer, therefore you're getting -1 after reading from BufferedInputStream
Have a look at the BufferedInputStream source code: http://www.docjar.com/html/api/java/io/BufferedInputStream.java.html
http://docs.oracle.com/javase/7/docs/api/java/io/BufferedInputStream.html#BufferedInputStream%28java.io.InputStream%29
Looks like the BufferedInputStream uses the InputStream for the actions performed with the data stream. The Buffered class simply implements a buffer array for internal use.
Not sure what you could use instead, apart from perhaps copying the InputStream so that you have a second object to call.
BufferedInputStream will pre-load data from the underlying InputStream in batches, which will trigger respective move of the underlying InputStream position. If the buffer size is enough to consume all data from the underlying stream in one go you may well observe the behavior you describe.
Two things:
Any API that accepts a stream as input parameter is probably going to use that stream, so it is unreasonable for the caller to expect the stream to remain in any kind of usable state. Perhaps it would have been better for the java stream classes to enforce single ownership somehow to make that clearer.
As a special case, BufferedInputStream is going to use the underlying stream that it "wraps" because it achieves (a limited form of) mark and reset by buffering block reads, as others have pointed out.
private static class MybufferedInputStream extends BufferedInputStream {
public MybufferedInputStream(InputStream in) {
super(in);
}
public int getBufferSize(){
int i=0;
for (Byte byte1 : super.buf) {
if (byte1!=0) {
i++;
}
}
return i;
}
}
then you can call the getBufferSize() after read() to see the difference between a small file and a larger file.

Java InputStream != Readable

I am using java.util.Scanner for things such as nextInt(), and all was working fine as long as I was using a java.lang.Readable (one and only constructor argument). However, when I changed to using an InputStream instead, Scanner.nextInt() never returns. Do you know why?
My implementation of the InputStream looks like this:
private static class ConsoleInputStream extends InputStream {
...
private byte[] buffer;
private int bufferIndex;
public int read() throws IOException {
...
while (...) {
if (buffer != null && bufferIndex < buffer.length) {
return buffer[bufferIndex++]; // THE COMMENT!
}
...
}
...
}
}
When I print the data by THE COMMENT I (correctly) get stuff like '1','2','\n' for "12\n", etc. Is there some Scanner hookup, unbeknown to me, that cause this behavior?
From the javadocs for InputStream's read() method:
"Returns: the next byte of data, or -1 if the end of the stream is reached."
I would guess that you're never returning -1?
I think the problem is with your self-built InputStream. Why did you build your own, rather than simply simply using System.in ?
Update:
Wanted input from a JTextField.
OK, got it. It usually doesn't make sense to use I/O handling to read stuff that's already available, in character form, but I can see how that would make your life easier with Scanner.
Still, you could probably have saved yourself some coding and grief by using a "finished" InputStream. What comes to mind is
InputStream is = new ByteArrayInputStream(myTextField.getText().getBytes());
Java I/O is yucky. Be glad the bright people from Sun have encapsulated most of it away for you.

How do I unit test a Java method which uses ProcessBuilder and Process?

I have a Java method which starts up a Process with ProcessBuilder, and pipes its output into a byte array, and then returns its byte array when the process is finished.
Pseudo-code:
ProcessBuilder b = new ProcessBuilder("my.exe")
Process p = b.start();
... // get output from process, close process
What would be the best way to go about unit testing this method? I haven't found a way to mock ProcessBuilder (it's final), even with the incredibly awesome JMockit, it gives me a NoClassDefFoundError:
java.lang.NoClassDefFoundError: test/MockProcessBuilder
at java.lang.ProcessBuilder.<init>(ProcessBuilder.java)
at mypackage.MyProcess.start(ReportReaderWrapperImpl.java:97)
at test.MyProcessTest.testStart(ReportReaderWrapperImplTest.java:28)
Any thoughts?
Answer - As Olaf recommended, I ended up refactoring those lines to an interface
Process start(String param) throws IOException;
I now pass an instance of this interface into the class I wanted to test (in its constructor), normally using a default implementation with the original lines. When I want to test I simply use a mock implementation of the interface. Works like a charm, though I do wonder if I'm over-interfacing here...
Shield yourself from the classes to be mocked. Create an interface either for doing what you really want (e.g. hiding the fact that external processes are involved at all) or only for Process and ProcessBuilder.
You don't want to test, that ProcessBuilder and Process work, only that you can work with their output. When you create an interface one trivial implementation (that can be inspected easily) delegates to ProcessBuilder and Process, another implementation mocks this behaviour. Later on you might even have another implementation that does what you need without starting another process.
With newer releases of JMockit (0.98+) you should be able to easily mock JRE classes like Process and ProcessBuilder. So, no need to create interfaces just for testing...
Full example (using JMockit 1.16):
public class MyProcessTest
{
public static class MyProcess {
public byte[] run() throws IOException, InterruptedException {
Process process = new ProcessBuilder("my.exe").start();
process.waitFor();
// Simplified example solution:
InputStream processOutput = process.getInputStream();
byte[] output = new byte[8192];
int bytesRead = processOutput.read(output);
return Arrays.copyOf(output, bytesRead);
}
}
#Test
public void runProcessReadingItsOutput(#Mocked final ProcessBuilder pb)
throws Exception
{
byte[] expectedOutput = "mocked output".getBytes();
final InputStream output = new ByteArrayInputStream(expectedOutput);
new Expectations() {{ pb.start().getInputStream(); result = output; }};
byte[] processOutput = new MyProcess().run();
assertArrayEquals(expectedOutput, processOutput);
}
}

Categories