package com.limegroup.bittorrent.metadata; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.limewire.bittorrent.BTData; import org.limewire.bittorrent.BTData.BTFileData; import org.limewire.util.Base32; import org.limewire.util.NameValue; import org.limewire.util.StringUtils; import org.limewire.util.URIUtils; import com.limegroup.gnutella.metadata.MetaData; import com.limegroup.gnutella.xml.LimeXMLDocument; /** * Allows accessing metadata about the torrent through the MetaData interface. */ public class TorrentMetaData implements MetaData { public static final String TORRENT_SCHEMA = "http://www.limewire.com/schemas/torrent.xsd"; public static final String INFO_HASH = "torrents__torrent__infohash__"; public static final String ANNOUNCE = "torrents__torrent__announce__"; public static final String LENGTH = "torrents__torrent__length__"; public static final String NAME = "torrents__torrent__name__"; public static final String PRIVATE = "torrents__torrent__private__"; public static final String PIECE_LENGTH = "torrents__torrent__piecelength__"; public static final String WEBSEEDS = "torrents__torrent__webseeds__"; public static final String FILE_PATHS = "torrents__torrent__filepaths__"; public static final String FILE_LENGTHS = "torrents__torrent__filelengths__"; private List<NameValue<String>> nameValues; public TorrentMetaData(BTData data) throws IOException { nameValues = Collections.unmodifiableList(buildNameValueList(data)); } @Override public String getSchemaURI() { return TORRENT_SCHEMA; } @Override public void populate(LimeXMLDocument doc) { throw new UnsupportedOperationException("not implemented yet"); } private List<NameValue<String>> buildNameValueList(BTData data) throws IOException { NameValueListBuilder builder = new NameValueListBuilder(); builder.add(INFO_HASH, Base32.encode(data.getInfoHash())); try { builder.add(ANNOUNCE, URIUtils.toURI(data.getAnnounce()).toASCIIString()); } catch (URISyntaxException ie) { throw new IOException(ie); } Long length = data.getLength(); if (length != null) { builder.add(LENGTH, length); } builder.add(NAME, data.getName()); // unimportant information not parsed and sent for now // builder.add(PIECE_LENGTH, data.getPieceLength()); boolean isPrivate = data.isPrivate(); if (isPrivate) { builder.add(PRIVATE, Boolean.TRUE.toString()); } String uris = StringUtils.explode(data.getWebSeeds(), "\t"); if (uris.length() > 0) { builder.add(WEBSEEDS, uris); } List<BTFileData> files = data.getFiles(); if (files != null) { List<String> filePaths = new ArrayList<String>(files.size()); List<Long> fileLengths = new ArrayList<Long>(files.size()); for (BTFileData file : files) { try { filePaths.add(URIUtils.toURI(file.getPath()).toASCIIString()); } catch (URISyntaxException e) { throw new IOException(e); } fileLengths.add(file.getLength()); } builder.add(FILE_PATHS, StringUtils.explode(filePaths, "\t")); builder.add(FILE_LENGTHS, StringUtils.explode(fileLengths, "\t")); } return builder.toList(); } @Override public List<NameValue<String>> toNameValueList() { return nameValues; } private static class NameValueListBuilder { private List<NameValue<String>> values = new ArrayList<NameValue<String>>(); public void add(String name, String value) { values.add(new NameValue<String>(name, value)); } public void add(String name, URI uri) { values.add(new NameValue<String>(name, uri.toASCIIString())); } public void add(String name, long value) { values.add(new NameValue<String>(name, Long.toString(value))); } List<NameValue<String>> toList() { return values; } } }