public static Bulletin loadFromFileAsNewDraft(MartusCrypto security, File inputFile)
     throws Exception {
   Bulletin original = new Bulletin(security);
   BulletinZipImporter.loadFromFile(original, inputFile, security);
   Bulletin imported =
       new Bulletin(
           security, original.getTopSectionFieldSpecs(), original.getBottomSectionFieldSpecs());
   imported.createDraftCopyOf(original, null);
   return imported;
 }
 public static void loadFromZipString(Bulletin b, String zipString, MartusCrypto sigVerifier)
     throws IOException, StreamableBase64.InvalidBase64Exception {
   File tempFile = null;
   try {
     tempFile = StreamableBase64.decodeToTempFile(zipString);
     BulletinZipImporter.loadFromFile(b, tempFile, sigVerifier);
   } finally {
     if (tempFile != null) tempFile.delete();
   }
 }
  public static void loadFromFile(Bulletin b, File inputFile, MartusCrypto verifier)
      throws IOException {
    b.clearAllUserData();
    ZipFile zip = new ZipFile(inputFile);
    try {

      BulletinHeaderPacket header = b.getBulletinHeaderPacket();

      ZipEntry headerEntry = null;
      Enumeration entries = zip.entries();
      while (entries.hasMoreElements()) headerEntry = (ZipEntry) entries.nextElement();
      InputStreamWithSeek headerIn = new ZipEntryInputStreamWithSeek(zip, headerEntry);
      try {
        header.loadFromXml(headerIn, verifier);
        if (!header.getLocalId().equals(headerEntry.getName()))
          throw new IOException("Misnamed header entry");
      } catch (Exception e) {
        throw new IOException(e.getMessage());
      } finally {
        headerIn.close();
      }

      FieldDataPacket data = b.getFieldDataPacket();

      entries = zip.entries();
      ZipEntry dataEntry = zip.getEntry(header.getFieldDataPacketId());
      if (dataEntry == null) throw new IOException("Data packet not found");
      InputStreamWithSeek dataIn = new ZipEntryInputStreamWithSeek(zip, dataEntry);
      try {
        data.loadFromXml(dataIn, header.getFieldDataSignature(), verifier);
      } catch (MartusCrypto.DecryptionException e) {
        // TODO mark bulletin as not complete
      } catch (Exception e) {
        throw new IOException(e.getMessage());
      } finally {
        dataIn.close();
      }

      FieldDataPacket privateData = b.getPrivateFieldDataPacket();

      entries = zip.entries();
      ZipEntry privateDataEntry = zip.getEntry(header.getPrivateFieldDataPacketId());
      if (privateDataEntry == null) throw new IOException("Private data packet not found");
      InputStreamWithSeek privateDataIn = new ZipEntryInputStreamWithSeek(zip, privateDataEntry);
      try {
        privateData.loadFromXml(privateDataIn, header.getPrivateFieldDataSignature(), verifier);
      } catch (MartusCrypto.DecryptionException e) {
        // TODO Mark bulletin as not complete
      } catch (Exception e) {
        System.out.println(e);
        e.printStackTrace();
        throw new IOException(e.getMessage());
      } finally {
        privateDataIn.close();
      }

      AttachmentProxy[] attachments = b.getPublicAttachments();
      b.clearPublicAttachments();
      for (int i = 0; i < attachments.length; ++i) {
        final AttachmentProxy ap =
            BulletinZipImporter.extractZipAttachmentToFileProxy(verifier, zip, attachments[i]);
        b.addPublicAttachment(ap);
      }

      AttachmentProxy[] attachmentsPrivate = b.getPrivateAttachments();
      b.clearPrivateAttachments();
      for (int i = 0; i < attachmentsPrivate.length; ++i) {
        final AttachmentProxy ap =
            BulletinZipImporter.extractZipAttachmentToFileProxy(
                verifier, zip, attachmentsPrivate[i]);
        b.addPrivateAttachment(ap);
      }

      b.setAuthorizedToReadKeys(header.getAuthorizedToReadKeys());
    } catch (Exception e) {
      throw new IOException(e.getMessage());
    } finally {
      zip.close();
    }
  }