package hep.io.root.daemon.xrootd; import java.io.IOException; import java.io.InputStream; import java.net.Authenticator; import java.net.InetAddress; import java.net.PasswordAuthentication; import java.net.URL; import java.net.URLConnection; import java.util.logging.Logger; /** * The core class for dealing with root: protocol connections. * Currently only supports reading files. Currently only supports * plain text (insecure) authorization. * @author Tony Johnson */ public class XrootdURLConnection extends URLConnection { private String username; private String password; private String auth; // authorization mode to use private int bufferSize = 32768; private long date; private long fSize; private int flags; private static Logger logger = Logger.getLogger(XrootdURLConnection.class.getName()); public static final String XROOT_AUTHORIZATION_SCHEME = "scheme"; public static final String XROOT_AUTHORIZATION_SCHEME_ANONYMOUS = "anonymous"; public static final String XROOT_AUTHORIZATION_USER = "user"; public static final String XROOT_AUTHORIZATION_PASSWORD = "password"; public static final String XROOT_BUFFER_SIZE = "bufferSize"; private Session session; private int openStreamCount; private XrootdInputStreamFactory streamFactory; XrootdURLConnection(URL url, XrootdInputStreamFactory factory) { super(url); this.streamFactory = factory; } @Override public InputStream getInputStream() throws IOException { connect(); InputStream stream = streamFactory.createStream(this); openStreamCount++; return stream; } public void connect() throws IOException { if (connected) { return; } if (auth == null) { auth = System.getProperty("root.scheme"); } if (auth != null && auth.equalsIgnoreCase(XROOT_AUTHORIZATION_SCHEME_ANONYMOUS)) { username = XROOT_AUTHORIZATION_SCHEME_ANONYMOUS; try { password = System.getProperty("user.name") + "@" + InetAddress.getLocalHost().getCanonicalHostName(); } catch (SecurityException x) { password = "freehep-user@freehep.org"; } } if (username == null) { username = System.getProperty("root.user"); } if (password == null) { password = System.getProperty("root.password"); } // Check for username password, if not present, and if allowed, prompt the user. if ((password == null || username == null) && getAllowUserInteraction()) { int port = url.getPort(); if (port == -1) { port = XrootdProtocol.defaultPort; } PasswordAuthentication pa = Authenticator.requestPasswordAuthentication(url.getHost(), null, port, "root", "Username/Password required", auth); if (pa != null) { username = pa.getUserName(); password = new String(pa.getPassword()); } } if (password == null || username == null) { throw new IOException("Authorization Required"); } logger.fine("Opening rootd connection to: " + url); Destination dest = new Destination(url.getHost(), url.getPort(), username); session = new Session(dest); try { FileStatus status = session.stat(url.getFile()); fSize = status.getSize(); flags = status.getFlags(); date = status.getModTime().getTime(); // Prepare to do a checksum // FIXME: The file location may contain the original redirector, which may result // in the checksum being sent to the redirector if (!dest.equals(status.getFileLocation())) { session.close(); session = new Session(status.getFileLocation()); } connected = true; } catch (IOException t) { disconnect(); throw t; } } public void disconnect() throws IOException { if (session != null) { session.close(); session = null; } connected = false; } @Override public int getContentLength() { if (session == null) { return -1; } return (int) fSize; } public long getLongContentLength() { if (session == null) { return -1; } return fSize; } @Override public long getLastModified() { if (session == null) { return 0; } return date; } @Override public long getDate() { return getLastModified(); } public long getCheckSum() throws IOException { if (session == null) { return -1; } else { String result = session.query(XrootdProtocol.kXR_Qcksum, url.getFile()); String[] split = result.split(" "); return Long.parseLong(split[1]); } } @Override public void setRequestProperty(String key, String value) { if (key.equalsIgnoreCase(XROOT_AUTHORIZATION_USER)) { username = value; } else if (key.equalsIgnoreCase(XROOT_AUTHORIZATION_PASSWORD)) { password = value; } else if (key.equalsIgnoreCase(XROOT_AUTHORIZATION_SCHEME)) { auth = value; } else if (key.equalsIgnoreCase(XROOT_BUFFER_SIZE)) { bufferSize = Integer.parseInt(value); } } int getBufferSize() { return bufferSize; } Session getSession() { return session; } void streamClosed() throws IOException { openStreamCount--; if (openStreamCount == 0) { disconnect(); } } @Override protected void finalize() throws Throwable { disconnect(); super.finalize(); } }