/**
   * Convert the contents of a ProfileManager to XML and write the XML to the given writer.
   *
   * @param profileManager the ProfileManager
   * @param writer the XMLStreamWriter to write to
   */
  public static void marshal(ProfileManager profileManager, XMLStreamWriter writer) {
    try {
      writer.writeStartElement("userprofiles");
      String profileVersion = getProfileVersion(profileManager.getProfileObjectStoreWriter());
      writer.writeAttribute(MetadataManager.PROFILE_FORMAT_VERSION, profileVersion);
      List<?> usernames = profileManager.getProfileUserNames();

      for (Object userName : usernames) {
        Profile profile = profileManager.getProfile((String) userName);
        LOG.info("Writing profile: " + profile.getUsername());
        long startTime = System.currentTimeMillis();

        ProfileBinding.marshal(
            profile,
            profileManager.getProductionObjectStore(),
            writer,
            profileManager.getVersion(),
            getClassKeys(profileManager.getProductionObjectStore()));

        long totalTime = System.currentTimeMillis() - startTime;
        LOG.info(
            "Finished writing profile: " + profile.getUsername() + " took " + totalTime + "ms.");
      }

      TrackManagerBinding.marshal(profileManager.getProfileObjectStoreWriter(), writer);
      writer.writeEndElement();
    } catch (XMLStreamException e) {
      throw new RuntimeException(e);
    }
  }
 /** {@inheritDoc} */
 @Override
 public void startElement(String uri, String localName, String qName, Attributes attrs)
     throws SAXException {
   if ("userprofile".equals(qName)) {
     if (attrs.getValue("username") != null) {
       username = attrs.getValue("username");
     }
     if (attrs.getValue("password") != null) {
       password = attrs.getValue("password");
     }
     if (attrs.getValue("apikey") != null) {
       apiKey = attrs.getValue("apikey");
     }
     if (attrs.getValue("localAccount") != null) {
       isLocal = Boolean.parseBoolean(attrs.getValue("localAccount"));
     }
     if (attrs.getValue("superUser") != null) {
       isSuperUser = Boolean.parseBoolean(attrs.getValue("superUser"));
     }
   }
   if ("bags".equals(qName)) {
     savedBags = new LinkedHashMap();
     invalidBags = new LinkedHashMap();
     bagsValues = new LinkedHashMap();
     subHandler =
         new InterMineBagHandler(
             profileManager.getProfileObjectStoreWriter(),
             osw,
             savedBags,
             invalidBags,
             bagsValues);
   }
   if ("shared-bags".equals(qName)) {
     sharedBags = new ArrayList<Map<String, String>>();
     subHandler = new SharedBagHandler(sharedBags);
   }
   if ("template-queries".equals(qName)) {
     savedTemplates = new LinkedHashMap();
     subHandler = new TemplateQueryHandler(savedTemplates, version);
   }
   if ("queries".equals(qName)) {
     savedQueries = new LinkedHashMap();
     subHandler = new SavedQueryHandler(savedQueries, savedBags, version);
   }
   if ("tags".equals(qName)) {
     subHandler = new TagHandler(username, tags);
   }
   if ("preferences".equals(qName)) {
     subHandler = new PreferencesHandler(preferences);
   }
   if ("invitations".equals(qName)) {
     subHandler = invitationHandler;
   }
   if (subHandler != null) {
     subHandler.startElement(uri, localName, qName, attrs);
   }
 }
  /**
   * Method called when user has finished updating a constraint.
   *
   * @param mapping The ActionMapping used to select this instance
   * @param form The optional ActionForm bean for this request (if any)
   * @param request The HTTP request we are processing
   * @param response The HTTP response we are creating
   * @return an ActionForward object defining where control goes next
   * @exception Exception if the application business logic throws an exception
   */
  @Override
  public ActionForward execute(
      ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
      throws Exception {
    HttpSession session = request.getSession();
    final InterMineAPI im = SessionMethods.getInterMineAPI(session);
    ProfileManager pm = im.getProfileManager();
    String username = ((CreateAccountForm) form).getUsername();
    String password = ((CreateAccountForm) form).getPassword();
    pm.createNewProfile(username, password);
    Properties webProperties = SessionMethods.getWebProperties(session.getServletContext());
    try {
      MailUtils.email(username, webProperties);
      if (((CreateAccountForm) form).getMailinglist()
          && webProperties.getProperty("mail.mailing-list") != null
          && webProperties.getProperty("mail.mailing-list").length() > 0) {
        MailUtils.subscribe(username, webProperties);
      }
      SessionMethods.recordMessage(
          "You have successfully created an account, and logged in.", session);
    } catch (Exception e) {
      SessionMethods.recordError("Failed to send confirmation email", session);
    }

    /*
     * This code generates an MD5 key for the given username which is then
     * encoded in Hexadecimal. This could later be used for account
     * activation.
     *
     * try { MessageDigest md5 = MessageDigest.getInstance("MD5"); byte[]
     * buffer = username.getBytes(); md5.update(buffer); byte[] array =
     * md5.digest(); String encoded = HexBin.encode(array); } catch
     * (NoSuchAlgorithmException e) { }
     */
    doLogin(request, username, password);
    return new ActionForward("/begin.do");
  }
 /** {@inheritDoc} */
 @Override
 public void startElement(String uri, String localName, String qName, Attributes attrs)
     throws SAXException {
   if ("userprofiles".equals(qName)) {
     String value = attrs.getValue(MetadataManager.PROFILE_FORMAT_VERSION);
     if (value == null) {
       version = 0;
     } else {
       version = Integer.parseInt(value);
     }
     ObjectStoreWriter userprofileOsw = profileManager.getProfileObjectStoreWriter();
     Connection con = null;
     try {
       con = ((ObjectStoreInterMineImpl) userprofileOsw).getConnection();
       if (!DatabaseUtil.tableExists(con, "bagvalues")) {
         DatabaseUtil.createBagValuesTables(con);
       }
     } catch (SQLException sqle) {
       LOG.error("Problem retrieving connection", sqle);
     } finally {
       ((ObjectStoreInterMineImpl) userprofileOsw).releaseConnection(con);
     }
     sharedBagsByUsers = new HashedMap();
   }
   if ("userprofile".equals(qName)) {
     startTime = System.currentTimeMillis();
     profileHandler = new ProfileHandler(profileManager, osw, version, sharedBagsByUsers);
   }
   if (profileHandler != null) {
     profileHandler.startElement(uri, localName, qName, attrs);
   }
   if ("tracks".equals(qName)) {
     trackHandler = new TrackManagerHandler(profileManager.getProfileObjectStoreWriter());
   }
   if (trackHandler != null) {
     trackHandler.startElement(uri, localName, qName, attrs);
   }
 }
  /** {@inheritDoc} */
  @Override
  public void endElement(String uri, String localName, String qName) throws SAXException {
    super.endElement(uri, localName, qName);
    if ("userprofile".equals(qName)) {
      Profile profile;
      profile = profileHandler.getProfile();
      profileManager.createProfileWithoutBags(profile);
      try {
        Map<String, Set<BagValue>> bagValues = profileHandler.getBagsValues();
        for (StorableBag bag : profile.getAllBags().values()) {
          bag.saveWithBagValues(profile.getUserId(), bagValues.get(bag.getName()));
        }
      } catch (ObjectStoreException ose) {
        throw new SAXException(ose);
      }
      // Must come after the bags themselves have been stored.
      try {
        SharedBagManager.getInstance(profileManager);
        profileHandler.getInvitationHandler().storeInvites(profile);
      } catch (SQLException e) {
        LOG.error("Cannot store invitations", e);
        if (abortOnError) {
          throw new SAXException(e);
        }
      }
      Set<Tag> tags = profileHandler.getTags();
      TagManager tagManager = new TagManagerFactory(profile.getProfileManager()).getTagManager();
      for (Tag tag : tags) {
        try {
          tagManager.addTag(tag.getTagName(), tag.getObjectIdentifier(), tag.getType(), profile);
        } catch (TagManager.TagException e) {
          LOG.error("Cannot add tag: " + tag.toString(), e);
          if (abortOnError) {
            throw new SAXException(e);
          }
        } catch (RuntimeException e) {
          LOG.error("Error adding tag: " + tag.toString(), e);
          if (abortOnError) {
            throw new SAXException(e);
          }
        }
      }
      profile.getSearchRepository().receiveEvent(new MassTaggingEvent());
      profileHandler = null;
      long totalTime = System.currentTimeMillis() - startTime;
      LOG.info("Finished profile: " + profile.getUsername() + " took " + totalTime + "ms.");
    }
    if ("userprofiles".equals(qName)) {
      if (!sharedBagsByUsers.isEmpty()) {
        SharedBagManager sharedBagManager = SharedBagManager.getInstance(profileManager);
        String bagName, dateCreated;
        for (String user : sharedBagsByUsers.keySet()) {
          List<Map<String, String>> sharedBags = sharedBagsByUsers.get(user);
          if (!sharedBags.isEmpty()) {
            for (Map<String, String> sharedBag : sharedBags) {
              bagName = sharedBag.get("name");
              dateCreated = sharedBag.get("dateCreated");
              sharedBagManager.shareBagWithUser(bagName, dateCreated, user);
            }
          }
        }
      }
    }
    if (profileHandler != null) {
      profileHandler.endElement(uri, localName, qName);
    }

    if (trackHandler != null) {
      trackHandler.endElement(uri, localName, qName);
    }
  }