public String addFile( String filename, String alt_filename, String  mimetype, METSMetadata md ) throws Exception {
	// read in the file
	File fileobj = new File( filename );
  InputStream is = new FileInputStream(fileobj);
  long length = fileobj.length();
	byte[] arr = new byte[ (int) length ];

// Read in the bytes
  int offset = 0;
  int numRead = 0;
  while (offset < arr.length
         && (numRead=is.read(arr, offset, arr.length-offset)) >= 0) {
		offset += numRead;
  }

	is.close();

	// change the filename to remove any path.
	filename = fileobj.getName();

	// replace the physical filename with an alternative, if specified

	if( alt_filename != null ) {
		filename = alt_filename;
	}
	
	MessageDigest md5 = MessageDigest.getInstance( "MD5" );
	md5.update( arr );

	String digest = dumpBytes( md5.digest() ) ;

	String fileid = filename;
	String dmdid  = "DMD-" + fileid+"-" + dmd_idx;

	dmd_idx++;

	Element file = (Element) doc.createElement( "file" );
	file.setAttribute( "ID", fileid );
	file.setAttribute( "DMDID" , dmdid );
	file.setAttribute( "CHECKSUMTYPE", "MD5" );
	file.setAttribute( "CHECKSUM", digest );
	file.setAttribute( "MIMETYPE", mimetype );

	Element flocate = (Element) doc.createElement( "FLocat" );
	flocate.setAttribute( "LOCTYPE", "URL" );
	flocate.setAttribute( "xlink:type", "simple" );
	flocate.setAttribute( "xlink:href", filename );

	file.appendChild( flocate );
	filegrp.appendChild( file );


	// DMD object
	Element xmlData = addMetadata( dmdid );

	dmd_hash.put ( dmdid, xmlData );

	//  structmap
	{
		Element e1 = (Element) doc.createElement( "div" );
		e1.setAttribute( "ID", dmdid +  "-struct" );
		Element e2 = (Element) doc.createElement( "fptr" );
		e2.setAttribute( "FILEID", fileid );
		e1.appendChild( e2 );
		structmap.appendChild( e1 );
	}

	set_md( xmlData, md ); 


	// write data to zipfile
	ZipEntry ze = new ZipEntry( filename );
	zout.putNextEntry( ze );
	zout.write( arr, 0, arr.length );

	return dmdid;
}