/**
     * Imports data stored in an export file
     *
     * @param apps The applications in the PRISMS environment
     * @return Whether the import succeeded
     */
    public boolean importData(PrismsApplication[] apps) {
      try {
        java.util.HashMap<String, PrismsSynchronizer> syncs;
        java.util.HashMap<String, PrismsApplication> appsByNS;
        syncs = new java.util.HashMap<String, PrismsSynchronizer>();
        appsByNS = new java.util.HashMap<String, PrismsApplication>();
        for (PrismsApplication app : apps) {
          for (prisms.arch.event.PrismsProperty<?> property : app.getGlobalProperties()) {
            if (PrismsSynchronizer.class.isAssignableFrom(property.getType())) {
              PrismsSynchronizer sync = (PrismsSynchronizer) app.getGlobalProperty(property);
              if (sync == null || !(sync.getKeeper() instanceof DBRecordKeeper)) continue;
              syncs.put(((DBRecordKeeper) sync.getKeeper()).getNamespace(), sync);
              appsByNS.put(((DBRecordKeeper) sync.getKeeper()).getNamespace(), app);
            }
          }
        }
        if (!theJsonReader.goToProperty("data")) {
          log.error("No \"data\" property found in exported data");
          return false;
        }

        JsonSerialReader.StructState rootState = theJsonReader.startArray();
        JsonSerialReader.JsonParseItem item;
        StringBuilder message = new StringBuilder();
        message
            .append("Imported PRISMS data from ")
            .append(prisms.util.PrismsUtils.print(theExportDataTime))
            .append(" (");
        prisms.util.PrismsUtils.printTimeLength(
            System.currentTimeMillis() - theExportDataTime, message, false);
        message.append(" old).");
        for (item = theJsonReader.getNextItem(true, false);
            item instanceof JsonSerialReader.ObjectItem;
            item = theJsonReader.getNextItem(true, false)) {
          JsonSerialReader.StructState syncState = theJsonReader.save();
          try {
            /* The current state is now just past the beginning of one synchronizer's exported data */
            if (!"namespace".equals(theJsonReader.getNextProperty())) {
              message.append("\n\tNamespace expected in sync data set");
              continue;
            }
            String namespace = theJsonReader.parseString();
            PrismsSynchronizer sync = syncs.get(namespace);
            if (sync == null) {
              message.append("\n\tNo synchronizer loaded with namespace " + namespace);
              continue;
            }
            message.append("\n\tImporting data for namespace \"").append(namespace).append('"');
            String version;
            if (!"version".equals(theJsonReader.getNextProperty())) version = null;
            else version = theJsonReader.parseString();
            boolean preAI = ((DBRecordKeeper) sync.getKeeper()).hasAbsoluteIntegrity();
            ((DBRecordKeeper) sync.getKeeper()).setAbsoluteIntegrity(true);
            try {
              importData(appsByNS.get(namespace), sync, version, theJsonReader, message);
            } catch (Exception e) {
              message.append("\n\t\tImport failed: ").append(e);
              log.error("Could not import data for synchronizer " + namespace, e);
            } finally {
              ((DBRecordKeeper) sync.getKeeper()).setAbsoluteIntegrity(preAI);
            }
          } finally {
            theJsonReader.endObject(syncState);
          }
        }
        theJsonReader.endArray(rootState);
        int passwords = 0;
        if (theJsonReader.goToProperty("passwords")) {
          rootState = theJsonReader.startArray();
          prisms.util.LongList pwdData = new prisms.util.LongList();
          for (item = theJsonReader.getNextItem(true, false);
              item instanceof JsonSerialReader.ObjectItem;
              item = theJsonReader.getNextItem(true, false)) {
            JsonSerialReader.StructState pwdState = theJsonReader.save();
            try {
              theJsonReader.goToProperty("userName");
              String userName = theJsonReader.parseString();
              User user = apps[0].getEnvironment().getUserSource().getUser(userName);
              if (user == null) continue;
              theJsonReader.goToProperty("passwordData");
              theJsonReader.startArray();
              Number num;
              do {
                num = theJsonReader.parseNumber();
                if (num != null) pwdData.add(num.longValue());
              } while (num != null);
              theJsonReader.endArray(null);
              try {
                apps[0].getEnvironment().getUserSource().setPassword(user, pwdData.toArray(), true);
              } catch (prisms.arch.PrismsException e) {
                log.error("Could not set password for user " + userName, e);
              }
              passwords++;
              pwdData.clear();
            } finally {
              theJsonReader.endObject(pwdState);
            }
          }
          theJsonReader.endArray(rootState);
        }
        message.append("\n\tImported ").append(passwords).append(" passwords");
        log.info(message.toString());
        return true;
      } catch (Exception e) {
        log.error("Could not read or parse exported data", e);
        return false;
      } finally {
        close();
      }
    }