Java tutorial
package com.limegroup.gnutella.archive; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import java.net.SocketException; import java.net.UnknownHostException; import java.util.Collection; import java.util.Iterator; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPConnectionClosedException; import org.apache.commons.net.ftp.FTPReply; import org.apache.commons.net.io.CopyStreamException; import org.apache.xerces.dom3.bootstrap.DOMImplementationRegistry; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.ls.DOMImplementationLS; import org.w3c.dom.ls.LSSerializer; import com.limegroup.gnutella.util.CommonUtils; abstract class ArchiveContribution extends AbstractContribution { /** * @param media * One of ArchiveConstants.MEDIA_* * * @throws IllegalArgumentException * If media is not valid */ public ArchiveContribution(String username, String password, String title, String description, int media) throws DescriptionTooShortException { this(username, password, title, description, media, Archives.defaultCollectionForMedia(media), Archives.defaultTypesForMedia(media)); } public ArchiveContribution(String username, String password, String title, String description, int media, int collection, int type) throws DescriptionTooShortException { setUsername(username); setPassword(password); setTitle(title); setDescription(description); setMedia(media); setCollection(collection); setType(type); } abstract protected String getFtpServer(); abstract protected String getFtpPath(); abstract protected boolean isFtpDirPreMade(); abstract protected void checkin() throws IOException; /** * * @throws UnknownHostException * If the hostname cannot be resolved. * * @throws SocketException * If the socket timeout could not be set. * * @throws FTPConnectionClosedException * If the connection is closed by the server. * * @throws LoginFailedException * If the login fails. * * @throws DirectoryChangeFailedException * If changing to the directory provided by the internet * archive fails. * * @throws CopyStreamException * If an I/O error occurs while in the middle of * transferring a file. * * @throws IOException * If an I/O error occurs while sending a command or * receiving a reply from the server * * @throws IllegalStateException * If the contribution object is not ready to upload * (no username, password, server, etc. set) * or if java's xml parser is configured badly */ public void upload() throws UnknownHostException, SocketException, FTPConnectionClosedException, LoginFailedException, DirectoryChangeFailedException, CopyStreamException, RefusedConnectionException, IOException { final int NUM_XML_FILES = 2; final String META_XML_SUFFIX = "_meta.xml"; final String FILES_XML_SUFFIX = "_files.xml"; final String username = getUsername(); final String password = getPassword(); if (getFtpServer() == null) { throw new IllegalStateException("ftp server not set"); } if (getFtpPath() == null) { throw new IllegalStateException("ftp path not set"); } if (username == null) { throw new IllegalStateException("username not set"); } if (password == null) { throw new IllegalStateException("password not set"); } // calculate total number of files and bytes final String metaXmlString = serializeDocument(getMetaDocument()); final String filesXmlString = serializeDocument(getFilesDocument()); final byte[] metaXmlBytes = metaXmlString.getBytes(); final byte[] filesXmlBytes = filesXmlString.getBytes(); final int metaXmlLength = metaXmlBytes.length; final int filesXmlLength = filesXmlBytes.length; final Collection files = getFiles(); final int totalFiles = NUM_XML_FILES + files.size(); final String[] fileNames = new String[totalFiles]; final long[] fileSizes = new long[totalFiles]; final String metaXmlName = getIdentifier() + META_XML_SUFFIX; fileNames[0] = metaXmlName; fileSizes[0] = metaXmlLength; final String filesXmlName = getIdentifier() + FILES_XML_SUFFIX; fileNames[1] = filesXmlName; fileSizes[1] = filesXmlLength; int j = 2; for (Iterator i = files.iterator(); i.hasNext();) { final File f = (File) i.next(); fileNames[j] = f.getRemoteFileName(); fileSizes[j] = f.getFileSize(); j++; } // init the progress mapping for (int i = 0; i < fileSizes.length; i++) { _fileNames2Progress.put(fileNames[i], new UploadFileProgress(fileSizes[i])); _totalUploadSize += fileSizes[i]; } FTPClient ftp = new FTPClient(); try { // first connect if (isCancelled()) { return; } ftp.enterLocalPassiveMode(); if (isCancelled()) { return; } ftp.connect(getFtpServer()); final int reply = ftp.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { throw new RefusedConnectionException(getFtpServer() + "refused FTP connection"); } // now login if (isCancelled()) { return; } if (!ftp.login(username, password)) { throw new LoginFailedException(); } try { // try to change the directory if (!ftp.changeWorkingDirectory(getFtpPath())) { // if changing fails, make the directory if (!isFtpDirPreMade() && !ftp.makeDirectory(getFtpPath())) { throw new DirectoryChangeFailedException(); } // now change directory, if it fails again bail if (isCancelled()) { return; } if (!ftp.changeWorkingDirectory(getFtpPath())) { throw new DirectoryChangeFailedException(); } } if (isCancelled()) { return; } connected(); // upload xml files uploadFile(metaXmlName, new ByteArrayInputStream(metaXmlBytes), ftp); uploadFile(filesXmlName, new ByteArrayInputStream(filesXmlBytes), ftp); // now switch to binary mode if (isCancelled()) { return; } ftp.setFileType(FTP.BINARY_FILE_TYPE); // upload contributed files for (final Iterator i = files.iterator(); i.hasNext();) { final File f = (File) i.next(); uploadFile(f.getRemoteFileName(), new FileInputStream(f.getIOFile()), ftp); } } catch (InterruptedIOException ioe) { // we've been requested to cancel return; } finally { ftp.logout(); // we don't care if logging out fails } } finally { try { ftp.disconnect(); } catch (IOException e) { } // don't care if disconnecting fails } // now tell the Internet Archive that we're done if (isCancelled()) { return; } checkinStarted(); if (isCancelled()) { return; } checkin(); if (isCancelled()) { return; } checkinCompleted(); } /** * * @param fileName * @param input * The input stream (not necessarily buffered). * This stream will be closed by this method */ private void uploadFile(String remoteFileName, InputStream input, FTPClient ftp) throws InterruptedIOException, IOException { fileStarted(remoteFileName); final InputStream fileStream = new BufferedInputStream(new UploadMonitorInputStream(input, this)); try { if (isCancelled()) { throw new InterruptedIOException(); } ftp.storeFile(remoteFileName, fileStream); } finally { fileStream.close(); } if (isCancelled()) { throw new InterruptedIOException(); } fileCompleted(); } /** * @throws IllegalStateException * If java's xml parser configuration is bad */ private Document getMetaDocument() { /* * Sample _meta.xml file: * * <metadata> * <collection>opensource_movies</collection> * <mediatype>movies</mediatype> * <title>My Home Movie</title> * <runtime>2:30</runtime> * <director>Joe Producer</director> * </metadata> * */ final String METADATA_ELEMENT = "metadata"; final String COLLECTION_ELEMENT = "collection"; final String MEDIATYPE_ELEMENT = "mediatype"; final String TITLE_ELEMENT = "title"; final String DESCRIPTION_ELEMENT = "description"; final String LICENSE_URL_ELEMENT = "licenseurl"; final String UPLOAD_APPLICATION_ELEMENT = "upload_application"; final String APPID_ATTR = "appid"; final String APPID_ATTR_VALUE = "LimeWire"; final String VERSION_ATTR = "version"; final String UPLOADER_ELEMENT = "uploader"; final String IDENTIFIER_ELEMENT = "identifier"; final String TYPE_ELEMENT = "type"; try { final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); final DocumentBuilder db = dbf.newDocumentBuilder(); final Document document = db.newDocument(); final Element metadataElement = document.createElement(METADATA_ELEMENT); document.appendChild(metadataElement); final Element collectionElement = document.createElement(COLLECTION_ELEMENT); metadataElement.appendChild(collectionElement); collectionElement.appendChild(document.createTextNode(Archives.getCollectionString(getCollection()))); final Element mediatypeElement = document.createElement(MEDIATYPE_ELEMENT); metadataElement.appendChild(mediatypeElement); mediatypeElement.appendChild(document.createTextNode(Archives.getMediaString(getMedia()))); final Element typeElement = document.createElement(TYPE_ELEMENT); metadataElement.appendChild(typeElement); typeElement.appendChild(document.createTextNode(Archives.getTypeString(getType()))); final Element titleElement = document.createElement(TITLE_ELEMENT); metadataElement.appendChild(titleElement); titleElement.appendChild(document.createTextNode(getTitle())); final Element descriptionElement = document.createElement(DESCRIPTION_ELEMENT); metadataElement.appendChild(descriptionElement); descriptionElement.appendChild(document.createTextNode(getDescription())); final Element identifierElement = document.createElement(IDENTIFIER_ELEMENT); metadataElement.appendChild(identifierElement); identifierElement.appendChild(document.createTextNode(getIdentifier())); final Element uploadApplicationElement = document.createElement(UPLOAD_APPLICATION_ELEMENT); metadataElement.appendChild(uploadApplicationElement); uploadApplicationElement.setAttribute(APPID_ATTR, APPID_ATTR_VALUE); uploadApplicationElement.setAttribute(VERSION_ATTR, CommonUtils.getLimeWireVersion()); final Element uploaderElement = document.createElement(UPLOADER_ELEMENT); metadataElement.appendChild(uploaderElement); uploaderElement.appendChild(document.createTextNode(getUsername())); //take licenseurl from the first File final Iterator filesIterator = getFiles().iterator(); if (filesIterator.hasNext()) { final File firstFile = (File) filesIterator.next(); final String licenseUrl = firstFile.getLicenseUrl(); if (licenseUrl != null) { final Element licenseUrlElement = document.createElement(LICENSE_URL_ELEMENT); metadataElement.appendChild(licenseUrlElement); licenseUrlElement.appendChild(document.createTextNode(licenseUrl)); } } // now build user-defined elements final Map userFields = getFields(); for (final Iterator i = userFields.keySet().iterator(); i.hasNext();) { final Object field = i.next(); final Object value = userFields.get(field); if (field instanceof String) { final Element e = document.createElement((String) field); metadataElement.appendChild(e); if (value != null && value instanceof String) { e.appendChild(document.createTextNode((String) value)); } } } return document; } catch (final ParserConfigurationException e) { final IllegalStateException ise = new IllegalStateException(); ise.initCause(e); throw ise; } } /** * @throws IllegalStateException * If java's xml configuration is bad * @return */ private Document getFilesDocument() { /* * Sample _files.xml file: * * <files> * <file name="MyHomeMovie.mpeg" source="original"> * <runtime>2:30</runtime> * <format>MPEG2</format> * </file> * </files> * */ final String FILES_ELEMENT = "files"; try { final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); final DocumentBuilder db = dbf.newDocumentBuilder(); final Document document = db.newDocument(); final Element filesElement = document.createElement(FILES_ELEMENT); document.appendChild(filesElement); Collection files = getFiles(); for (final Iterator i = files.iterator(); i.hasNext();) { final File file = (File) i.next(); final Element fileElement = file.getElement(document); filesElement.appendChild(fileElement); } return document; } catch (final ParserConfigurationException e) { final IllegalStateException ise = new IllegalStateException(); ise.initCause(e); throw ise; } } /** * @throws IllegalStateException * If java's DOMImplementationLS class is screwed up or * this code is buggy * @param document * @return */ private String serializeDocument(Document document) { try { System.setProperty(DOMImplementationRegistry.PROPERTY, "org.apache.xerces.dom.DOMImplementationSourceImpl"); final DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance(); final DOMImplementationLS impl = (DOMImplementationLS) registry.getDOMImplementation("LS"); final LSSerializer writer = impl.createLSSerializer(); final String str = writer.writeToString(document); return str; } catch (final ClassNotFoundException e) { final IllegalStateException ise = new IllegalStateException(); ise.initCause(e); throw ise; } catch (final InstantiationException e) { final IllegalStateException ise = new IllegalStateException(); ise.initCause(e); throw ise; } catch (final IllegalAccessException e) { final IllegalStateException ise = new IllegalStateException(); ise.initCause(e); throw ise; } } }