Je n'ai aimé aucune des implémentations (car elles utilisent un Regex qui est une opération coûteuse, ou une bibliothèque qui est excessive si vous n'avez besoin que d'une seule méthode), alors j'ai fini par utiliser la classe java.net.URI avec certains vérifications supplémentaires, et en limitant les protocoles à: http, https, fichier, ftp, mailto, news, urn.
Et oui, intercepter des exceptions peut être une opération coûteuse, mais probablement pas aussi mauvaise que les expressions régulières:
final static Set<String> protocols, protocolsWithHost;
static {
protocolsWithHost = new HashSet<String>(
Arrays.asList( new String[]{ "file", "ftp", "http", "https" } )
);
protocols = new HashSet<String>(
Arrays.asList( new String[]{ "mailto", "news", "urn" } )
);
protocols.addAll(protocolsWithHost);
}
public static boolean isURI(String str) {
int colon = str.indexOf(':');
if (colon < 3) return false;
String proto = str.substring(0, colon).toLowerCase();
if (!protocols.contains(proto)) return false;
try {
URI uri = new URI(str);
if (protocolsWithHost.contains(proto)) {
if (uri.getHost() == null) return false;
String path = uri.getPath();
if (path != null) {
for (int i=path.length()-1; i >= 0; i--) {
if ("?<>:*|\"".indexOf( path.charAt(i) ) > -1)
return false;
}
}
}
return true;
} catch ( Exception ex ) {}
return false;
}