//package ch.cyberduck.core;
//
///*
// * Copyright (c) 2005 David Kocher. All rights reserved.
// * http://cyberduck.ch/
// *
// * This program is free software; you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation; either version 2 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * Bug fixes, suggestions and comments should be sent to:
// * dkocher@cyberduck.ch
// */
//
//import ch.cyberduck.core.i18n.Locale;
////import ch.cyberduck.ui.cocoa.foundation.NSAutoreleasePool;
//
//import org.apache.log4j.Logger;
//
//import com.apple.dnssd.*;
//
//import java.util.Collections;
//import java.util.HashSet;
//import java.util.Map;
//import java.util.Set;
//import java.util.concurrent.ConcurrentHashMap;
//
///**
// * @version $Id: Rendezvous.java 5607 2009-12-06 19:42:22Z dkocher $
// */
//public class Rendezvous implements BrowseListener, ResolveListener {
// private static Logger log = Logger.getLogger(Rendezvous.class);
//
// /**
// * sftp-ssh
// * Secure File Transfer Protocol over SSH
// * Bryan Cole <bryan.cole at teraview.com>
// * Protocol description: draft-ietf-secsh-filexfer-13.txt
// * Defined TXT keys: u=<username> p=<password> path=<path>
// */
// private static final String SERVICE_TYPE_SFTP = "_sftp-ssh._tcp.";
// /**
// * ftp
// * File Transfer
// * Service name originally allocated for Jon Postel <postel at isi.edu>
// * Now advertised and browsed-for by numerous independent
// * server and client implementations.
// * Protocol description: RFC 959
// * Defined TXT keys: u=<username> p=<password> path=<path>
// */
// private static final String SERVICE_TYPE_FTP = "_ftp._tcp.";
// /**
// * webdav
// * World Wide Web Distributed Authoring and Versioning (WebDAV)
// * Y. Y. Goland <yarong at microsoft.com>
// * Protocol description: RFC 2518
// * Defined TXT keys: u=<username> p=<password> path=<path>
// */
// private static final String SERVICE_TYPE_WEBDAV = "_webdav._tcp";
// /**
// * webdavs
// * WebDAV over SSL/TLS
// * Y. Y. Goland <yarong at microsoft.com>
// * Protocol description: RFC 2518
// * Defined TXT keys: u=<username> p=<password> path=<path>
// */
// private static final String SERVICE_TYPE_WEBDAV_TLS = "_webdavs._tcp";
//
// private static final String[] serviceTypes = new String[]{
// SERVICE_TYPE_SFTP, SERVICE_TYPE_FTP, SERVICE_TYPE_WEBDAV, SERVICE_TYPE_WEBDAV_TLS
// };
//
// private Map<String, Host> services;
// private Map<String, DNSSDService> browsers;
//
// private static Rendezvous instance = null;
//
// private static final Object lock = new Object();
//
// public static Rendezvous instance() {
// synchronized(lock) {
// if(null == instance) {
// instance = new Rendezvous();
// }
// }
// return instance;
// }
//
// private Rendezvous() {
// log.debug("Rendezvous");
// this.services = new ConcurrentHashMap<String, Host>();
// this.browsers = new ConcurrentHashMap<String, DNSSDService>();
// }
//
// /**
// * Start browsing for rendezvous servcices for all registered service types
// */
// public void init() {
// log.debug("init");
// try {
// for(String protocol : serviceTypes) {
// log.info("Adding Rendezvous service listener for " + protocol);
// this.browsers.put(protocol, DNSSD.browse(protocol, this));
// }
// }
// catch(DNSSDException e) {
// log.error(e.getMessage());
// this.quit();
// }
// }
//
// /**
// * Halt all service discvery browsers
// */
// public void quit() {
// for(String protocol : serviceTypes) {
// log.info("Removing Rendezvous service listener for " + protocol);
// DNSSDService service = this.browsers.get(protocol);
// if(null == service) {
// continue;
// }
// service.stop();
// }
// }
//
// private Set<RendezvousListener> listeners =
// Collections.synchronizedSet(new HashSet<RendezvousListener>());
//
// private RendezvousListener notifier = new RendezvousListener() {
//
// public void serviceResolved(final String servicename, final String hostname) {
// log.info("Service resolved:" + servicename);
// RendezvousListener[] l = listeners.toArray(
// new RendezvousListener[listeners.size()]);
// for(RendezvousListener listener : l) {
// listener.serviceResolved(servicename, hostname);
// }
// }
//
// public void serviceLost(final String servicename) {
// log.info("Service lost:" + servicename);
// RendezvousListener[] l = listeners.toArray(
// new RendezvousListener[listeners.size()]);
// for(RendezvousListener listener : l) {
// listener.serviceLost(servicename);
// }
// }
// };
//
// /**
// * Register a listener to be notified
// *
// * @param listener
// */
// public void addListener(RendezvousListener listener) {
// listeners.add(listener);
// }
//
// /**
// * Remove the listener from the notification queue
// *
// * @param listener
// */
// public void removeListener(RendezvousListener listener) {
// listeners.remove(listener);
// }
//
// /**
// * @param identifier The full service domain name
// * @return The host this name maps to or null if none is found
// */
// public Host getServiceWithIdentifier(String identifier) {
// log.debug("getService:" + identifier);
// return services.get(identifier);
// }
//
// /**
// * @param displayedName The name returned by #getDisplayedName
// * @return The host this name maps to or null if none is found
// */
// public Host getServiceWithDisplayedName(String displayedName) {
// synchronized(this) {
// for(Host h : services.values()) {
// if(h.getNickname().equals(displayedName)) {
// return h;
// }
// }
// }
// log.warn("No identifier for displayed name:" + displayedName);
// return null;
// }
//
// /**
// * @return The number of services found; 0 <= services < n
// */
// public int numberOfServices() {
// return services.size();
// }
//
// public Host getService(int index) {
// return services.values().toArray(new Host[services.size()])[index];
// }
//
// /**
// * @param index
// * @return A nicely formatted informative string
// */
// public String getDisplayedName(int index) {
// if(index < this.numberOfServices()) {
// return services.values().toArray(new Host[services.size()])[index].getNickname();
// }
// return Locale.localizedString("Unknown");
// }
//
// /**
// * @param identifier The full service domain name
// * @return A nicely formatted informative string
// */
// public String getDisplayedName(String identifier) {
// Host host = services.get(identifier);
// if(null == host) {
// return Locale.localizedString("Unknown");
// }
// return host.getNickname();
// }
//
// /**
// * @param browser
// * @param flags
// * @param ifIndex
// * @param servicename
// * @param regType
// * @param domain
// */
// public void serviceFound(DNSSDService browser, int flags, int ifIndex, String servicename,
// String regType, String domain) {
// log.debug("serviceFound:" + servicename);
// try {
// DNSSD.resolve(flags, ifIndex, servicename, regType, domain, this);
// }
// catch(DNSSDException e) {
// log.error(e.getMessage());
// }
// }
//
// /**
// * @param browser
// * @param flags
// * @param ifIndex
// * @param serviceName
// * @param regType
// * @param domain
// */
// public void serviceLost(DNSSDService browser, int flags, int ifIndex, String serviceName,
// String regType, String domain) {
// log.debug("serviceLost:" + serviceName);
//// final NSAutoreleasePool pool = NSAutoreleasePool.push();
// try {
// String identifier = DNSSD.constructFullName(serviceName, regType, domain);
// if(null == this.services.remove(identifier)) {
// return;
// }
// notifier.serviceLost(identifier);
// }
// catch(DNSSDException e) {
// log.error(e.getMessage());
// }
// finally {
//// pool.drain();
// }
// }
//
// /**
// * @param resolver
// * @param errorCode
// */
// public void operationFailed(DNSSDService resolver, int errorCode) {
// log.warn("operationFailed:" + errorCode);
// resolver.stop();
// }
//
// /**
// * @param resolver
// * @param flags
// * @param ifIndex
// * @param fullname
// * @param hostname
// * @param port
// * @param txtRecord
// */
// public void serviceResolved(DNSSDService resolver, int flags, int ifIndex,
// final String fullname, final String hostname, int port, TXTRecord txtRecord) {
// log.debug("serviceResolved:" + hostname);
//// final NSAutoreleasePool pool = NSAutoreleasePool.push();
// try {
// final Protocol protocol = this.getProtocol(fullname, port);
// if(null == protocol) {
// log.warn("Unknown service type:" + fullname);
// return;
// }
// final Host host = new Host(protocol, hostname, port);
// log.debug("TXT Record:" + txtRecord);
// if(txtRecord.contains("u")) {
// host.getCredentials().setUsername(txtRecord.getValueAsString("u"));
// }
// else {
// host.getCredentials().setUsername(null);
// }
// if(txtRecord.contains("p")) {
// host.getCredentials().setPassword(txtRecord.getValueAsString("p"));
// }
// if(txtRecord.contains("path")) {
// host.setDefaultPath(Path.normalize(txtRecord.getValueAsString("path")));
// }
// if(null == this.services.put(fullname, host)) {
// this.notifier.serviceResolved(fullname, hostname);
// }
// }
// finally {
// // Note: When the desired results have been returned, the client MUST terminate
// // the resolve by calling DNSSDService.stop().
// resolver.stop();
//// pool.drain();
// }
// }
//
// /**
// * @param serviceType
// * @return Null if no protocol can be found for the given Rendezvous service type.
// * @see "http://developer.apple.com/qa/qa2001/qa1312.html"
// */
// public Protocol getProtocol(final String serviceType, final int port) {
// if(serviceType.contains(SERVICE_TYPE_SFTP)) {
// return Protocol.SFTP;
// }
// if(serviceType.contains(SERVICE_TYPE_FTP)) {
// return Protocol.FTP;
// }
// if(serviceType.contains(SERVICE_TYPE_WEBDAV)) {
// return Protocol.WEBDAV;
// }
// if(serviceType.contains(SERVICE_TYPE_WEBDAV_TLS)) {
// return Protocol.WEBDAV_SSL;
// }
// return null;
// }
//}