2017-06-30 1 views
1

J'ai une classe qui prend un InputStream comme argument pour lire des données.Vérifiez si Java InputStream provient de Socket

public Foo { 
    private DataInput in; 

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

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

Parfois, ce InputStream peut venir d'une prise, par exemple,

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

Ma question est, est-il possible de vérifier à partir de Foo que le flux d'entrée provient de la prise, par exemple, il est un réseau E/S plutôt que E/S locales? Puisque le

socket.getInputStream 

appelle la classe abstraite. Je ne sais pas quelle implémentation de flux d'entrée concrète tester. Edit: la motivation est qu'il existe un gros logiciel Java qui a cette structure. Foo est créé dans de nombreux endroits. Certains endroits avec un flux d'entrée de fichier tandis que d'autres avec un flux d'entrée de socket. Le logiciel peut mal fonctionner lorsque la lecture se fait sur le réseau. Donc, je veux voir s'il est possible de faire du traçage pour différencier les deux scénarios pour ce logiciel sans changer une grande partie de son code. J'utilise AspectJ pour écrire le calque dans l'espoir de ne pas créer beaucoup de désordre à ce logiciel existant.

+2

Non (du moins pas sans une solution à base de réflexion moche), puisque vous l'enveloppez dans un BufferedInputStream. Mais vous ne devriez pas avoir à faire attention: un InputStream est un InputStream. Qu'essayez-vous d'accomplir? –

+1

Non, vous avez écrit toute l'interface de 'Foo' pour être indépendant et isolé des sockets. Si vous voulez que 'Foo' connaisse les sockets, vous devrez lui donner un socket. – pvg

+0

J'ai besoin de faire un peu de traçage pour différencier quand Foo fait la lecture de réseau au lieu de lire le fichier local. – Oxdeadbeef

Répondre

1

Le problème est qu'un InputStream peut être un FilterInputStream qui est construit autour d'un autre InputStream et que la prise retourne juste un InputStream.

Une approche très saleté & poussette: trouver le InputStream racine, qui est récursive/boucle si elle est une instance de FilterInputStream, vérifiez son InputStream parent (champ de protection in). Ensuite, vérifiez la classe de la racine, le nom contient probablement "Socket" si elle provient d'un Socket. AspectJ idée (je n'ai pas beaucoup d'expérience avec elle): vous devriez être capable d'ajouter un aspect à la méthode getInputStream de Socket qui stocke le InputStream retourné dans une liste (ou similaire) pour vérification ultérieure, ou en quelque sorte marque ce InputStream (en ajoutant un drapeau/méthode?).

0

Vous pouvez créer 2 superclasses de flux d'entrée avant de les passer en classe Foo.

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 {} 

Ensuite, la classe Foo:

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