void importData( PrismsApplication app, PrismsSynchronizer sync, String version, JsonSerialReader jsr, StringBuilder message) throws java.io.IOException, SAJParser.ParseException { SyncRecord syncRecord = new SyncRecord( new PrismsCenter("Export"), SyncRecord.Type.AUTOMATIC, System.currentTimeMillis(), false); PrismsSynchronizer.SyncTransaction trans = sync.transact( version, true, syncRecord, false, new prisms.ui.UI.DefaultProgressInformer()); // Items PrismsSynchronizer.PS2ItemReader itemReader = new PrismsSynchronizer.PS2ItemReader(trans); if (!jsr.goToProperty("items")) { message.append("\n\t\tNo items property in sync data"); return; } int items = 0; org.json.simple.JSONObject obj; jsr.startArray(); obj = jsr.parseObject(); while (obj != null) { items++; try { itemReader.read(obj); } catch (PrismsRecordException e) { log.error("Error parsing item", e); } obj = jsr.parseObject(); } jsr.endArray(null); message.append("\n\t\t").append(items).append(" items"); PrismsCenter[] centers; try { centers = sync.getKeeper().getCenters(); } catch (PrismsRecordException e) { message.append("\n\t\t").append("Could not get centers"); log.error("Could not get centers", e); centers = null; } if (centers != null && trans.getImpl().getCentersProperty() != null) { PrismsCenter[] appCenters = centers; for (int i = 0; i < appCenters.length; i++) if (centers[i].getID() == 0) { // Don't include the "Here" center in the UI value appCenters = prisms.util.ArrayUtils.remove(appCenters, i); break; } app.setGlobalProperty( trans.getImpl().getCentersProperty(), appCenters, RecordUtils.TRANSACTION_EVENT_PROP, new prisms.records.RecordsTransaction()); } // Changes PrismsSynchronizer.ChangeReader changeReader = new PrismsSynchronizer.ChangeReader(trans, null, itemReader, 0); if (!jsr.goToProperty("changes")) { message.append("\n\t\tNo changes property in sync data"); return; } int changes = 0; jsr.startArray(); obj = jsr.parseObject(); while (obj != null) { changes++; changeReader.readChange(obj); obj = jsr.parseObject(); } jsr.endArray(null); message.append(", ").append(changes).append(" changes"); changeReader = null; itemReader = null; // Sync records if (centers != null) { if (jsr.goToProperty("syncRecords")) { int syncRecords = 0; jsr.startArray(); while (jsr.getNextItem(true, false) instanceof JsonSerialReader.ObjectItem) { JsonSerialReader.StructState centerState = jsr.save(); try { if (!jsr.goToProperty("id")) { message.append("\n\t\tID missing in sync records group"); break; } int centerID = jsr.parseInt(); PrismsCenter center = null; for (PrismsCenter c : centers) if (c.getID() == centerID) { center = c; break; } if (center == null) { log.warn("No such center with ID " + centerID); continue; } if (!jsr.goToProperty("syncRecords")) { message.append("\n\t\tsyncRecords missing in sync records group"); continue; } jsr.startArray(); while (jsr.getNextItem(true, false) instanceof JsonSerialReader.ObjectItem) { JsonSerialReader.StructState srState = jsr.save(); try { if (!jsr.goToProperty("id")) { log.warn("No id property in sync record"); continue; } int srID = jsr.parseInt(); if (!jsr.goToProperty("parallelID")) { log.warn("No parallelID property in sync record"); continue; } int parallelID = jsr.parseInt(); if (!jsr.goToProperty("syncType")) { log.warn("No syncType property in sync record"); continue; } String typeName = jsr.parseString(); SyncRecord.Type type = SyncRecord.Type.byName(typeName); if (type == null) { log.warn("Unrecognized sync type in sync record: " + typeName); continue; } if (!jsr.goToProperty("time")) { log.warn("No time property in sync record"); continue; } long time = jsr.parseLong(); if (!jsr.goToProperty("isImport")) { log.warn("No isImport property in sync record"); continue; } boolean isImport = jsr.parseBoolean(); if (!jsr.goToProperty("syncError")) { log.warn("No syncError property in sync record"); continue; } Object syncError = jsr.parseNext(false); SyncRecord sr = new SyncRecord(center, type, time, isImport); sr.setID(srID); sr.setParallelID(parallelID); if (syncError instanceof String) sr.setSyncError((String) syncError); else if (syncError == JsonSerialReader.NULL) sr.setSyncError(null); else String.class.cast(syncError); try { sync.getKeeper().putSyncRecord(sr); } catch (PrismsRecordException e) { log.error("Could not persist sync record", e); continue; } syncRecords++; if (!jsr.goToProperty("associated")) { log.warn("No associated property in sync record"); continue; } prisms.util.LongList assocIDs = new prisms.util.LongList(); prisms.util.BooleanList assocErrors = new prisms.util.BooleanList(); jsr.startArray(); while (jsr.getNextItem(true, false) instanceof JsonSerialReader.ObjectItem) { if (!jsr.goToProperty("id")) { log.warn("No id for associated change"); jsr.endObject(null); continue; } assocIDs.add(jsr.parseLong()); if (jsr.goToProperty("error")) assocErrors.add(jsr.parseBoolean()); else assocErrors.add(false); jsr.endObject(null); } jsr.endArray(null); ChangeRecord[] assocChanges; try { assocChanges = sync.getKeeper().getItems(assocIDs.toArray()); } catch (PrismsRecordException e) { log.error("Could not get associated changes", e); continue; } for (int i = 0; i < assocChanges.length; i++) { if (assocChanges[i] != null) try { sync.getKeeper().associate(assocChanges[i], sr, assocErrors.get(i)); } catch (PrismsRecordException e) { log.error("Could not associated change", e); } } } finally { jsr.endObject(srState); } } jsr.endArray(null); } finally { jsr.endObject(centerState); } } jsr.endArray(null); message.append(", ").append(syncRecords).append(" sync records"); } } // Latest changes if (jsr.goToProperty("latestChanges")) { JsonSerialReader.StructState rootState = jsr.startArray(); while (jsr.getNextItem(true, false) instanceof JsonSerialReader.ObjectItem) { JsonSerialReader.StructState lcState = jsr.save(); try { if (!jsr.goToProperty("center")) { log.warn("No center for latest change entry"); continue; } int centerID = jsr.parseInt(); if (!jsr.goToProperty("subjectCenter")) { log.warn("No subjectCenter for latest change entry"); continue; } int subjectCenter = jsr.parseInt(); if (!jsr.goToProperty("latestChange")) { log.warn("No latestChange for latest change entry"); continue; } long changeTime = jsr.parseLong(); try { sync.getKeeper().setLatestChange(centerID, subjectCenter, changeTime); } catch (PrismsRecordException e) { log.error("Could not set latest change", e); } } finally { jsr.endObject(lcState); } } jsr.endArray(rootState); } }
/** * Exports all synchronize-enabled PRISMS data to a file to be imported later * * @param ui The user interface to communicate with * @param global Whether to export ALL data available to synchronization instead of just the * local data and local modifications * @return Whether the export succeeded */ public boolean exportData(prisms.ui.UI ui, boolean global) { prisms.ui.UI.DefaultProgressInformer pi = new prisms.ui.UI.DefaultProgressInformer(); pi.setProgressText("Configuring PRISMS applications"); ui.startTimedTask(pi); try { for (PrismsApplication app : theApps) { if (!app.isConfigured()) { pi.setProgressText("Configuring " + app.getName()); // Configure the application. Can't be done except by the PrismsServer prisms.util.PrismsServiceConnector conn = new prisms.util.PrismsServiceConnector( theApps[0].getEnvironment().getIDs().getLocalInstance().location, app.getName(), app.getClients()[0].getName(), "System"); try { conn.getConnector() .setTrustManager( new javax.net.ssl.X509TrustManager() { public void checkClientTrusted( java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {} public void checkServerTrusted( java.security.cert.X509Certificate[] chain, String authType) throws java.security.cert.CertificateException {} public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } }); } catch (java.security.GeneralSecurityException e) { log.error("Could not set trust manager for service connector", e); } conn.setUserSource(theApps[0].getEnvironment().getUserSource()); log.debug("Application " + app.getName() + " is not yet configured. Configuring."); try { conn.init(); conn.logout(true); } catch (java.io.IOException e) { if (!app.isConfigured()) { ui.error( "Could not configure application " + app.getName() + ". Export data cannot proceed."); log.error("Could not configure application " + app.getName(), e); return false; } } if (!app.isConfigured()) { ui.error( "Could not configure application " + app.getName() + ". Export data cannot proceed."); log.error("Could not configure application " + app.getName()); return false; } } } return exportData(ui, pi, global); } finally { pi.setDone(); } }
/** * 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(); } }
boolean exportData(prisms.ui.UI ui, prisms.ui.UI.DefaultProgressInformer pi, boolean global) { java.io.File exportFile = new java.io.File( theApps[0].getEnvironment().getLogger().getExposedDir() + ".exportedData.dat"); if (exportFile.exists() && !prisms.util.FileSegmentizerOutputStream.delete(exportFile)) { ui.error( "Could not delete data exported on " + prisms.util.PrismsUtils.print(exportFile.lastModified())); log.error( "Could not delete data exported on " + prisms.util.PrismsUtils.print(exportFile.lastModified())); return false; } prisms.util.FileSegmentizerOutputStream fileStream = null; prisms.util.ExportStream exportStream; java.io.OutputStreamWriter streamWriter; JsonStreamWriter jsw; try { fileStream = new prisms.util.FileSegmentizerOutputStream(exportFile); exportStream = new prisms.util.ExportStream(fileStream); streamWriter = new java.io.OutputStreamWriter(exportStream); // streamWriter = new java.io.OutputStreamWriter(fileStream); jsw = new JsonStreamWriter(streamWriter); } catch (java.io.IOException e) { ui.error("Could not write data for export: " + e); log.error("Could not write data for export", e); if (fileStream != null) try { fileStream.close(); } catch (java.io.IOException e2) { } prisms.util.FileSegmentizerOutputStream.delete(exportFile); return false; } boolean success = false; try { jsw.startObject(); jsw.startProperty("exportTime"); jsw.writeNumber(Long.valueOf(System.currentTimeMillis())); jsw.startProperty("instance"); jsw.writeNumber(Integer.valueOf(theApps[0].getEnvironment().getIDs().getCenterID())); jsw.startProperty("hashing"); Hashing hashing = theApps[0].getEnvironment().getUserSource().getHashing(); jsw.startObject(); jsw.startProperty("multiples"); jsw.startArray(); for (long h : hashing.getPrimaryMultiples()) jsw.writeNumber(Long.valueOf(h)); jsw.endArray(); jsw.startProperty("modulos"); jsw.startArray(); for (long h : hashing.getPrimaryModulos()) jsw.writeNumber(Long.valueOf(h)); jsw.endArray(); jsw.endObject(); jsw.startProperty("data"); jsw.startArray(); java.util.HashSet<String> namespaces = new java.util.HashSet<String>(); for (PrismsApplication app : theApps) { 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; exportData(ui, sync, jsw, namespaces, pi, global); } } } jsw.endArray(); jsw.startProperty("passwords"); jsw.startArray(); for (User user : theApps[0].getEnvironment().getUserSource().getActiveUsers()) { prisms.arch.ds.UserSource.Password pwd = theApps[0].getEnvironment().getUserSource().getPassword(user); if (pwd == null) continue; jsw.startObject(); jsw.startProperty("userName"); jsw.writeString(user.getName()); jsw.startProperty("passwordData"); jsw.startArray(); for (long h : pwd.hash) jsw.writeNumber(Long.valueOf(h)); jsw.endArray(); jsw.endObject(); } jsw.endArray(); jsw.endObject(); jsw.close(); streamWriter.close(); fileStream.close(); success = true; ui.info( "Data has been exported. On server restart after rebuild," + " local data will be imported."); log.info( "Instance " + theApps[0].getEnvironment().getIDs().getLocalInstance().location + ": Data has been exported to " + exportFile.getCanonicalPath()); } catch (java.io.IOException e) { ui.error("Data export failed: " + e); log.error("Data export failed", e); } catch (prisms.records.PrismsRecordException e) { ui.error("Data export failed: " + e); log.error("Data export failed", e); } finally { if (!success) { try { fileStream.close(); } catch (java.io.IOException e2) { } prisms.util.FileSegmentizerOutputStream.delete(exportFile); } } return success; }