|
@@ -9,9 +9,6 @@ package net.ranides.assira.io;
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
import java.io.InputStream;
|
|
|
import java.io.OutputStream;
|
|
import java.io.OutputStream;
|
|
|
-import java.util.HashMap;
|
|
|
|
|
-import java.util.Map;
|
|
|
|
|
-import java.util.TreeMap;
|
|
|
|
|
import net.ranides.assira.events.EventListener;
|
|
import net.ranides.assira.events.EventListener;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -20,21 +17,136 @@ import net.ranides.assira.events.EventListener;
|
|
|
*/
|
|
*/
|
|
|
public final class AsyncStream {
|
|
public final class AsyncStream {
|
|
|
|
|
|
|
|
|
|
+ // InputDevice handle(IORequest) -> stream.read
|
|
|
|
|
+ //
|
|
|
|
|
+ // InputDriver read -> handle(IORequest)
|
|
|
|
|
+ //
|
|
|
|
|
+ // InputListener read -> stream.read -> handle(IOEvent)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ // OutputDevice handle(IORequest) -> stream.write
|
|
|
|
|
+ //
|
|
|
|
|
+ // OutputDriver write -> handle(IORequest)
|
|
|
|
|
+ //
|
|
|
|
|
+ // OutputListener write -> stream.write -> handle(IOEvent)
|
|
|
|
|
+
|
|
|
|
|
+ // komentarz: to chyba jest bez sensu, bo stream nie ma zaimplementowanego
|
|
|
|
|
+ // interfejsu w taki sposób, żeby działał w tle (np metody powinny zwracać
|
|
|
|
|
+ // wyniki).
|
|
|
|
|
+
|
|
|
|
|
+ // W praktyce InputListener oraz OutputListener mają sens w 100%.
|
|
|
|
|
+
|
|
|
|
|
+ // OutputDriver oraz OutputDevice mają sens w 75% (obsługa błędów leży)
|
|
|
|
|
+ // 1. OutputDriver nie rzuca wyjątków
|
|
|
|
|
+ // 2. OutputDevice nie wie, komu przesłać zdarzenia o wyjątkach
|
|
|
|
|
+
|
|
|
|
|
+ // InputDriver oraz InputDevice mają sens w 25% (obsługa wszystkiego leży)
|
|
|
|
|
+ // 3. InputDriver nie rzuca wyjątków
|
|
|
|
|
+ // 4. InputDriver nie zwraca sensownych wyników
|
|
|
|
|
+ // 5. InputDevice nie wie komu przesłać zdarzenia o wyjątkach
|
|
|
|
|
+ // 6. InputDevice nie wie komu zwrócić wyniki
|
|
|
|
|
+ // 7. kto ma tworzyć bufor na czytane dane ???
|
|
|
|
|
+ //
|
|
|
|
|
+ // W zasadzie to działa rozsądnie tylko dla układu:
|
|
|
|
|
+ // InputDriver -> InputDevice -> InputListener -> InputStream
|
|
|
|
|
+ //
|
|
|
|
|
+ // A poniższy układ do niczego się nie nadaje:
|
|
|
|
|
+ // InputDriver -> InputDevice -> InputStream
|
|
|
|
|
+
|
|
|
|
|
+ // Może więc tworzenie Device będzie możliwie tylko dla Listener'a?
|
|
|
|
|
+ // A dopiero Listener by był tworzony ze stream'a?
|
|
|
|
|
+ // To by rozwiązało problemy 2, 5, 6.
|
|
|
|
|
+
|
|
|
|
|
+ // Problem 7 powinno się rozwiązać alokując pamięć ZAWSZE. W końcu ten, co wywołał
|
|
|
|
|
+ // metodę, to chuj wie co będzie z tą tablicą za moment robić...
|
|
|
|
|
+
|
|
|
private AsyncStream() {
|
|
private AsyncStream() {
|
|
|
// utility class
|
|
// utility class
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private static abstract class InputAdapter extends InputStream implements EventListener<IOEvent> {
|
|
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * Uwaga! Wszystkie metody zwracają bezużyteczne wyniki. W zasadzie Bóg jeden
|
|
|
|
|
+ * wie po licho w ogóle implementujemy {@link InputStream}, bo i tak tego
|
|
|
|
|
+ * nie można nigdzie do normalnych metod przekazać.
|
|
|
|
|
+ *
|
|
|
|
|
+ * read -> handle(IORequest)
|
|
|
|
|
+ */
|
|
|
|
|
+ public static abstract class InputDriver extends InputStream implements EventListener<IORequest> {
|
|
|
|
|
+
|
|
|
|
|
+ public InputDriver() {
|
|
|
|
|
+ // do nothing
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public abstract void handleEvent(IORequest event);
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int read() throws IOException {
|
|
|
|
|
+ handleEvent(IORequest.read());
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int read(byte array[]) throws IOException {
|
|
|
|
|
+ handleEvent(IORequest.read(array.length));
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int read(byte array[], int offset, int length) throws IOException {
|
|
|
|
|
+ handleEvent(IORequest.read(length));
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public long skip(long delta) throws IOException {
|
|
|
|
|
+ handleEvent(IORequest.skip(delta));
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public int available() throws IOException {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void close() throws IOException {
|
|
|
|
|
+ handleEvent(IORequest.close());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public synchronized void mark(int readlimit) {
|
|
|
|
|
+ handleEvent(IORequest.mark(readlimit));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public synchronized void reset() throws IOException {
|
|
|
|
|
+ handleEvent(IORequest.reset());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public boolean markSupported() {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * read -> stream.read -> handle(IOEvent)
|
|
|
|
|
+ */
|
|
|
|
|
+ public static abstract class InputListener extends InputStream implements EventListener<IOEvent> {
|
|
|
|
|
+
|
|
|
private final InputStream istream;
|
|
private final InputStream istream;
|
|
|
|
|
|
|
|
- public InputAdapter(final InputStream istream) {
|
|
|
|
|
|
|
+ public InputListener(final InputStream istream) {
|
|
|
this.istream = istream;
|
|
this.istream = istream;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public abstract void handleEvent(IOEvent event);
|
|
public abstract void handleEvent(IOEvent event);
|
|
|
|
|
|
|
|
|
|
+ @Override
|
|
|
public int read() throws IOException {
|
|
public int read() throws IOException {
|
|
|
try {
|
|
try {
|
|
|
int data = istream.read();
|
|
int data = istream.read();
|
|
@@ -46,6 +158,7 @@ public final class AsyncStream {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Override
|
|
|
public int read(byte array[]) throws IOException {
|
|
public int read(byte array[]) throws IOException {
|
|
|
try {
|
|
try {
|
|
|
int delta = istream.read(array);
|
|
int delta = istream.read(array);
|
|
@@ -56,7 +169,8 @@ public final class AsyncStream {
|
|
|
throw cause;
|
|
throw cause;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
public int read(byte array[], int offset, int length) throws IOException {
|
|
public int read(byte array[], int offset, int length) throws IOException {
|
|
|
try {
|
|
try {
|
|
|
int delta = istream.read(array, offset, length);
|
|
int delta = istream.read(array, offset, length);
|
|
@@ -68,6 +182,7 @@ public final class AsyncStream {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Override
|
|
|
public long skip(long n) throws IOException {
|
|
public long skip(long n) throws IOException {
|
|
|
try {
|
|
try {
|
|
|
long delta = istream.skip(n);
|
|
long delta = istream.skip(n);
|
|
@@ -79,6 +194,7 @@ public final class AsyncStream {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Override
|
|
|
public int available() throws IOException {
|
|
public int available() throws IOException {
|
|
|
try {
|
|
try {
|
|
|
return istream.available();
|
|
return istream.available();
|
|
@@ -88,6 +204,7 @@ public final class AsyncStream {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Override
|
|
|
public void close() throws IOException {
|
|
public void close() throws IOException {
|
|
|
try {
|
|
try {
|
|
|
istream.close();
|
|
istream.close();
|
|
@@ -98,11 +215,13 @@ public final class AsyncStream {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Override
|
|
|
public synchronized void mark(int readlimit) {
|
|
public synchronized void mark(int readlimit) {
|
|
|
istream.mark(readlimit);
|
|
istream.mark(readlimit);
|
|
|
handleEvent(IOEvent.mark(readlimit));
|
|
handleEvent(IOEvent.mark(readlimit));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Override
|
|
|
public synchronized void reset() throws IOException {
|
|
public synchronized void reset() throws IOException {
|
|
|
try {
|
|
try {
|
|
|
istream.reset();
|
|
istream.reset();
|
|
@@ -113,39 +232,81 @@ public final class AsyncStream {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @Override
|
|
|
public boolean markSupported() {
|
|
public boolean markSupported() {
|
|
|
return istream.markSupported();
|
|
return istream.markSupported();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * write -> stream.write -> handle(IOEvent)
|
|
|
|
|
+ */
|
|
|
public static abstract class OutputListener extends OutputStream implements EventListener<IOEvent> {
|
|
public static abstract class OutputListener extends OutputStream implements EventListener<IOEvent> {
|
|
|
|
|
|
|
|
|
|
+ private final OutputStream ostream;
|
|
|
|
|
+
|
|
|
|
|
+ public OutputListener(OutputStream istream) {
|
|
|
|
|
+ this.ostream = istream;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
@Override
|
|
@Override
|
|
|
public abstract void handleEvent(IOEvent event);
|
|
public abstract void handleEvent(IOEvent event);
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public void write(int value) throws IOException {
|
|
public void write(int value) throws IOException {
|
|
|
- handleEvent(IOEvent.write(value));
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ ostream.write(value);
|
|
|
|
|
+ handleEvent(IOEvent.write(value));
|
|
|
|
|
+ } catch(IOException cause) {
|
|
|
|
|
+ handleEvent(IOEvent.failure(cause));
|
|
|
|
|
+ throw cause;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public void write(byte array[]) throws IOException {
|
|
public void write(byte array[]) throws IOException {
|
|
|
- handleEvent(IOEvent.write(array));
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ ostream.write(array);
|
|
|
|
|
+ handleEvent(IOEvent.write(array));
|
|
|
|
|
+ } catch(IOException cause) {
|
|
|
|
|
+ handleEvent(IOEvent.failure(cause));
|
|
|
|
|
+ throw cause;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public void write(byte array[], int offset, int length) throws IOException {
|
|
public void write(byte array[], int offset, int length) throws IOException {
|
|
|
- handleEvent(IOEvent.write(array, offset, length));
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ ostream.write(array, offset, length);
|
|
|
|
|
+ handleEvent(IOEvent.write(array, offset, length));
|
|
|
|
|
+ } catch(IOException cause) {
|
|
|
|
|
+ handleEvent(IOEvent.failure(cause));
|
|
|
|
|
+ throw cause;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public void flush() throws IOException {
|
|
public void flush() throws IOException {
|
|
|
- handleEvent(IOEvent.flush());
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ ostream.flush();
|
|
|
|
|
+ handleEvent(IOEvent.flush());
|
|
|
|
|
+ } catch(IOException cause) {
|
|
|
|
|
+ handleEvent(IOEvent.failure(cause));
|
|
|
|
|
+ throw cause;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public void close() throws IOException {
|
|
public void close() throws IOException {
|
|
|
- handleEvent(IOEvent.close());
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ ostream.close();
|
|
|
|
|
+ handleEvent(IOEvent.close());
|
|
|
|
|
+ } catch(IOException cause) {
|
|
|
|
|
+ handleEvent(IOEvent.failure(cause));
|
|
|
|
|
+ throw cause;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
}
|
|
}
|