/** * ATTENTION: This function is duplicated in the Web Of Trust plugin, please backport any changes. */ private synchronized void restoreDatabaseBackup(File databaseFile, File backupFile) throws IOException { Logger.warning(this, "Trying to restore database backup: " + backupFile.getAbsolutePath()); if (db != null) throw new RuntimeException("Database is opened already!"); if (backupFile.exists()) { try { FileUtil.secureDelete(databaseFile); } catch (IOException e) { Logger.warning(this, "Deleting of the database failed: " + databaseFile.getAbsolutePath()); } if (backupFile.renameTo(databaseFile)) { Logger.warning(this, "Backup restored!"); } else { throw new IOException( "Unable to rename backup file back to database file: " + databaseFile.getAbsolutePath()); } } else { throw new IOException("Cannot restore backup, it does not exist!"); } }
/** * Adds the node reference in the resources as a friend to the node this plugin is loaded. * * @return the corresponding PeerAdditionReturnCode indicating whether the bridge was added * successfully as a friend */ private PeerAdditionReturnCodes addFriendBridge() { SimpleFieldSet bridgeNodeFS; try { bridgeNodeFS = nodeRefHelper.getBridgeNodeRefFS(); } catch (IOException e) { Logger.error(this, "IO Exception while parsing bridge reference resource file"); return PeerAdditionReturnCodes.INTERNAL_ERROR; } PeerNode pn; try { pn = node.createNewDarknetNode(bridgeNodeFS, FRIEND_TRUST.HIGH, FRIEND_VISIBILITY.NO); ((DarknetPeerNode) pn).setPrivateDarknetCommentNote("Master Bridge"); } catch (FSParseException e) { return PeerAdditionReturnCodes.CANT_PARSE; } catch (PeerParseException e) { return PeerAdditionReturnCodes.CANT_PARSE; } catch (ReferenceSignatureVerificationException e) { return PeerAdditionReturnCodes.INVALID_SIGNATURE; } catch (Throwable t) { Logger.error(this, "Internal error adding reference :" + t.getMessage(), t); return PeerAdditionReturnCodes.INTERNAL_ERROR; } if (Arrays.equals(pn.getPubKeyHash(), node.getDarknetPubKeyHash())) { Logger.warning(this, "The bridge node reference file belongs to this node."); return PeerAdditionReturnCodes.TRY_TO_ADD_SELF; } if (!node.addPeerConnection(pn)) { return PeerAdditionReturnCodes.ALREADY_IN_REFERENCE; } return PeerAdditionReturnCodes.OK; }
public void setLanguage(LANGUAGE newLanguage) { try { CENOL10n.l10n = new PluginL10n(this, newLanguage); } catch (Exception e) { Logger.warning(this, "Could not set language to " + newLanguage); } }
@Override public synchronized void onFailure( InsertException e, BaseClientPutter state, ObjectContainer container) { try { if (e.getMode() == InsertException.COLLISION) { Logger.warning( this, "WoTOwnMessageList insert collided, trying to insert with higher index ..."); try { synchronized (mMessageManager) { // We must call getOwnMessageList() before calling onMessageListInsertFailed() because // the latter will increment the message list's // index, resulting in the ID of the message list changing - getIDFromURI would fail // with the old state.getURI() if we called it after // onMessageListInsertFailed() WoTOwnMessageList list = (WoTOwnMessageList) mMessageManager.getOwnMessageList( MessageListID.construct(state.getURI()).toString()); mMessageManager.onMessageListInsertFailed(state.getURI(), true); insertMessageList(list); } } catch (Exception ex) { Logger.error(this, "Inserting WoTOwnMessageList with higher index failed", ex); } } else { if (e.isFatal()) Logger.error(this, "WoTOwnMessageList insert failed", e); else Logger.warning(this, "WoTOwnMessageList insert failed non-fatally", e); mMessageManager.onMessageListInsertFailed(state.getURI(), false); } } catch (Exception ex) { Logger.error(this, "WoTOwnMessageList insert failed and failure handling threw", ex); } finally { removeInsert(state); Closer.close(((ClientPutter) state).getData()); } }
/** * ATTENTION: This function is duplicated in the Web Of Trust plugin, please backport any changes. */ private void closeDatabase() { if (db == null) { Logger.warning(this, "Terminated already."); return; } synchronized (Persistent.transactionLock(db)) { try { System.gc(); db.rollback(); System.gc(); db.close(); db = null; } catch (RuntimeException e) { Logger.error(this, "Error while closing database", e); } } }
public static NPFPacket create(byte[] plaintext, BasePeerNode pn) { NPFPacket packet = new NPFPacket(); if (pn == null) throw new IllegalArgumentException("Can't estimate an ack type of received packet"); int offset = 0; if (plaintext.length < (offset + 5)) { // Sequence number + the number of acks packet.error = true; return packet; } packet.sequenceNumber = ((plaintext[offset] & 0xFF) << 24) | ((plaintext[offset + 1] & 0xFF) << 16) | ((plaintext[offset + 2] & 0xFF) << 8) | (plaintext[offset + 3] & 0xFF); offset += 4; // Process received acks int numAckRanges = plaintext[offset++] & 0xFF; if (numAckRanges > 0) { try { int ack, prevAck = 0; for (int i = 0; i < numAckRanges; i++) { if (i == 0) { ack = ((plaintext[offset] & 0xFF) << 24) | ((plaintext[offset + 1] & 0xFF) << 16) | ((plaintext[offset + 2] & 0xFF) << 8) | (plaintext[offset + 3] & 0xFF); offset += 4; } else { int distanceFromPrevious = (plaintext[offset++] & 0xFF); if (distanceFromPrevious != 0) { ack = prevAck + distanceFromPrevious; } else { // Far offset ack = ((plaintext[offset] & 0xFF) << 24) | ((plaintext[offset + 1] & 0xFF) << 16) | ((plaintext[offset + 2] & 0xFF) << 8) | (plaintext[offset + 3] & 0xFF); offset += 4; } } int rangeSize = (plaintext[offset++] & 0xFF); for (int j = 1; j <= rangeSize; j++) { packet.acks.add(ack++); } prevAck = ack - 1; } } catch (ArrayIndexOutOfBoundsException e) { // The packet's length is not big enough packet.error = true; return packet; } } // Handle received message fragments int prevFragmentID = -1; while (offset < plaintext.length) { boolean shortMessage = (plaintext[offset] & 0x80) != 0; boolean isFragmented = (plaintext[offset] & 0x40) != 0; boolean firstFragment = (plaintext[offset] & 0x20) != 0; if (!isFragmented && !firstFragment) { // Padding or lossy messages. offset = tryParseLossyMessages(packet, plaintext, offset); break; } int messageID = -1; if ((plaintext[offset] & 0x10) != 0) { if (plaintext.length < (offset + 4)) { packet.error = true; return packet; } messageID = ((plaintext[offset] & 0x0F) << 24) | ((plaintext[offset + 1] & 0xFF) << 16) | ((plaintext[offset + 2] & 0xFF) << 8) | (plaintext[offset + 3] & 0xFF); offset += 4; } else { if (plaintext.length < (offset + 2)) { packet.error = true; return packet; } if (prevFragmentID == -1) { Logger.warning(NPFPacket.class, "First fragment doesn't have full message id"); packet.error = true; return packet; } messageID = prevFragmentID + (((plaintext[offset] & 0x0F) << 8) | (plaintext[offset + 1] & 0xFF)); offset += 2; } prevFragmentID = messageID; int requiredLength = offset + (shortMessage ? 1 : 2) + (isFragmented ? (shortMessage ? 1 : 3) : 0); if (plaintext.length < requiredLength) { packet.error = true; return packet; } int fragmentLength; if (shortMessage) { fragmentLength = plaintext[offset++] & 0xFF; } else { fragmentLength = ((plaintext[offset] & 0xFF) << 8) | (plaintext[offset + 1] & 0xFF); offset += 2; } int messageLength = -1; int fragmentOffset = 0; if (isFragmented) { int value; if (shortMessage) { value = plaintext[offset++] & 0xFF; } else { value = ((plaintext[offset] & 0xFF) << 8) | (plaintext[offset + 1] & 0xFF); offset += 2; } if (firstFragment) { messageLength = value; if (messageLength == fragmentLength) { Logger.warning( NPFPacket.class, "Received fragmented message, but fragment contains the entire message"); } } else { fragmentOffset = value; } } else { messageLength = fragmentLength; } if ((offset + fragmentLength) > plaintext.length) { Logger.error( NPFPacket.class, "Fragment doesn't fit in the received packet: offset is " + offset + " fragment length is " + fragmentLength + " plaintext length is " + plaintext.length + " message length " + messageLength + " message ID " + messageID + (pn == null ? "" : (" from " + pn.shortToString()))); packet.error = true; break; } byte[] fragmentData = Arrays.copyOfRange(plaintext, offset, offset + fragmentLength); offset += fragmentLength; packet.fragments.add( new MessageFragment( shortMessage, isFragmented, firstFragment, messageID, fragmentLength, messageLength, fragmentOffset, fragmentData, null)); } packet.length = offset; return packet; }
public static NPFPacket create(byte[] plaintext, BasePeerNode pn) { NPFPacket packet = new NPFPacket(); int offset = 0; if (plaintext.length < (offset + 5)) { // Sequence number + the number of acks packet.error = true; return packet; } packet.sequenceNumber = ((plaintext[offset] & 0xFF) << 24) | ((plaintext[offset + 1] & 0xFF) << 16) | ((plaintext[offset + 2] & 0xFF) << 8) | (plaintext[offset + 3] & 0xFF); offset += 4; // Process received acks int numAcks = plaintext[offset++] & 0xFF; if (plaintext.length < (offset + numAcks + (numAcks > 0 ? 3 : 0))) { packet.error = true; return packet; } int prevAck = 0; for (int i = 0; i < numAcks; i++) { int ack = 0; if (i == 0) { ack = ((plaintext[offset] & 0xFF) << 24) | ((plaintext[offset + 1] & 0xFF) << 16) | ((plaintext[offset + 2] & 0xFF) << 8) | (plaintext[offset + 3] & 0xFF); offset += 4; } else { ack = prevAck + (plaintext[offset++] & 0xFF); } packet.acks.add(ack); prevAck = ack; } // Handle received message fragments int prevFragmentID = -1; while (offset < plaintext.length) { boolean shortMessage = (plaintext[offset] & 0x80) != 0; boolean isFragmented = (plaintext[offset] & 0x40) != 0; boolean firstFragment = (plaintext[offset] & 0x20) != 0; if (!isFragmented && !firstFragment) { // Padding or lossy messages. offset = tryParseLossyMessages(packet, plaintext, offset); break; } int messageID = -1; if ((plaintext[offset] & 0x10) != 0) { if (plaintext.length < (offset + 4)) { packet.error = true; return packet; } messageID = ((plaintext[offset] & 0x0F) << 24) | ((plaintext[offset + 1] & 0xFF) << 16) | ((plaintext[offset + 2] & 0xFF) << 8) | (plaintext[offset + 3] & 0xFF); offset += 4; } else { if (plaintext.length < (offset + 2)) { packet.error = true; return packet; } if (prevFragmentID == -1) { Logger.warning(NPFPacket.class, "First fragment doesn't have full message id"); packet.error = true; return packet; } messageID = prevFragmentID + (((plaintext[offset] & 0x0F) << 8) | (plaintext[offset + 1] & 0xFF)); offset += 2; } prevFragmentID = messageID; int requiredLength = offset + (shortMessage ? 1 : 2) + (isFragmented ? (shortMessage ? 1 : 3) : 0); if (plaintext.length < requiredLength) { packet.error = true; return packet; } int fragmentLength; if (shortMessage) { fragmentLength = plaintext[offset++] & 0xFF; } else { fragmentLength = ((plaintext[offset] & 0xFF) << 8) | (plaintext[offset + 1] & 0xFF); offset += 2; } int messageLength = -1; int fragmentOffset = 0; if (isFragmented) { int value; if (shortMessage) { value = plaintext[offset++] & 0xFF; } else { value = ((plaintext[offset] & 0xFF) << 8) | (plaintext[offset + 1] & 0xFF); offset += 2; } if (firstFragment) { messageLength = value; if (messageLength == fragmentLength) { Logger.warning( NPFPacket.class, "Received fragmented message, but fragment contains the entire message"); } } else { fragmentOffset = value; } } else { messageLength = fragmentLength; } byte[] fragmentData = new byte[fragmentLength]; if ((offset + fragmentLength) > plaintext.length) { Logger.error( NPFPacket.class, "Fragment doesn't fit in the received packet: offset is " + offset + " fragment length is " + fragmentLength + " plaintext length is " + plaintext.length + " message length " + messageLength + " message ID " + messageID + (pn == null ? "" : (" from " + pn.shortToString()))); packet.error = true; break; } System.arraycopy(plaintext, offset, fragmentData, 0, fragmentLength); offset += fragmentLength; packet.fragments.add( new MessageFragment( shortMessage, isFragmented, firstFragment, messageID, fragmentLength, messageLength, fragmentOffset, fragmentData, null)); } packet.length = offset; return packet; }
/** * Compare a recently registered SendableRequest to what is already on the starter queue. If it is * better, kick out stuff from the queue until we are just over the limit. * * @param req * @param container */ public void maybeAddToStarterQueue( SendableRequest req, ObjectContainer container, SendableRequest[] mightBeActive) { short prio = req.getPriorityClass(container); if (logMINOR) Logger.minor(this, "Maybe adding to starter queue: prio=" + prio); synchronized (starterQueue) { boolean betterThanSome = false; int size = 0; PersistentChosenRequest prev = null; for (PersistentChosenRequest old : starterQueue) { if (old.request == req) { // Wait for a reselect. Otherwise we can starve other // requests. Note that this happens with persistent SBI's: // they are added at the new retry count before being // removed at the old retry count. if (logMINOR) Logger.minor(this, "Already on starter queue: " + old + " for " + req); return; } if (prev == old) Logger.error(this, "ON STARTER QUEUE TWICE: " + prev + " for " + prev.request); if (prev != null && prev.request == old.request) Logger.error( this, "REQUEST ON STARTER QUEUE TWICE: " + prev + " for " + prev.request + " vs " + old + " for " + old.request); boolean ignoreActive = false; if (mightBeActive != null) { for (SendableRequest tmp : mightBeActive) if (tmp == old.request) ignoreActive = true; } if (!ignoreActive) { if (container.ext().isActive(old.request)) Logger.warning( this, "REQUEST ALREADY ACTIVATED: " + old.request + " for " + old + " while checking request queue in maybeAddToStarterQueue for " + req); else if (logDEBUG) Logger.debug( this, "Not already activated for " + old + " in while checking request queue in maybeAddToStarterQueue for " + req); } else if (logMINOR) Logger.minor( this, "Ignoring active because just registered: " + old.request + " in maybeAddToStarterQueue for " + req); size += old.sizeNotStarted(); if (old.prio > prio) betterThanSome = true; if (old.request == req) return; prev = old; } if (size >= MAX_STARTER_QUEUE_SIZE && !betterThanSome) { if (logMINOR) Logger.minor( this, "Not adding to starter queue: over limit and req not better than any queued requests"); return; } } addToStarterQueue(req, container); trimStarterQueue(container); }
private void fillRequestStarterQueue(ObjectContainer container, ClientContext context) { synchronized (this) { if (fillingRequestStarterQueue) return; fillingRequestStarterQueue = true; } long now = System.currentTimeMillis(); try { if (logMINOR) Logger.minor( this, "Filling request queue... (SSK=" + isSSKScheduler + " insert=" + isInsertScheduler); long noLaterThan = Long.MAX_VALUE; boolean checkCooldownQueue = now > nextQueueFillRequestStarterQueue; if ((!isInsertScheduler) && checkCooldownQueue) { if (persistentCooldownQueue != null) noLaterThan = moveKeysFromCooldownQueue(persistentCooldownQueue, true, container); noLaterThan = Math.min( noLaterThan, moveKeysFromCooldownQueue(transientCooldownQueue, false, container)); } // If anything has been re-added, the request starter will have been woken up. short fuzz = -1; if (PRIORITY_SOFT.equals(choosenPriorityScheduler)) fuzz = -1; else if (PRIORITY_HARD.equals(choosenPriorityScheduler)) fuzz = 0; boolean added = false; synchronized (starterQueue) { if (logMINOR && (!isSSKScheduler) && (!isInsertScheduler)) { Logger.minor(this, "Scheduling CHK fetches..."); for (SendableRequest req : runningPersistentRequests) { boolean wasActive = container.ext().isActive(req); if (!wasActive) container.activate(req, 1); Logger.minor(this, "Running persistent request: " + req); if (!wasActive) container.deactivate(req, 1); } } // Recompute starterQueueLength int length = 0; PersistentChosenRequest old = null; for (PersistentChosenRequest req : starterQueue) { if (old == req) Logger.error(this, "DUPLICATE CHOSEN REQUESTS ON QUEUE: " + req); if (old != null && old.request == req.request) Logger.error( this, "DUPLICATE REQUEST ON QUEUE: " + old + " vs " + req + " both " + req.request); boolean ignoreActive = false; if (!ignoreActive) { if (container.ext().isActive(req.request)) Logger.warning( this, "REQUEST ALREADY ACTIVATED: " + req.request + " for " + req + " while checking request queue in filling request queue"); else if (logMINOR) Logger.minor( this, "Not already activated for " + req + " in while checking request queue in filling request queue"); } else if (logMINOR) Logger.minor(this, "Ignoring active because just registered: " + req.request); req.pruneDuplicates(ClientRequestScheduler.this); old = req; length += req.sizeNotStarted(); } if (logMINOR) Logger.minor( this, "Queue size: " + length + " SSK=" + isSSKScheduler + " insert=" + isInsertScheduler); if (length > MAX_STARTER_QUEUE_SIZE * 3 / 4) { if (length >= WARNING_STARTER_QUEUE_SIZE) Logger.error(this, "Queue already full: " + length); return; } } if ((!isSSKScheduler) && (!isInsertScheduler)) { Logger.minor(this, "Scheduling CHK fetches..."); } boolean addedMore = false; while (true) { SelectorReturn r; // Must synchronize on scheduler to avoid problems with cooldown queue. See notes on // CooldownTracker.clearCachedWakeup, which also applies to other cooldown operations. synchronized (this) { r = selector.removeFirstInner( fuzz, random, offeredKeys, starter, schedCore, schedTransient, false, true, Short.MAX_VALUE, isRTScheduler, context, container, now); } SendableRequest request = null; if (r != null && r.req != null) request = r.req; else { if (r != null && r.wakeupTime > 0 && noLaterThan > r.wakeupTime) { noLaterThan = r.wakeupTime; if (logMINOR) Logger.minor( this, "Waking up in " + TimeUtil.formatTime(noLaterThan - now) + " for cooldowns"); } } if (request == null) { synchronized (ClientRequestScheduler.this) { // Don't wake up for a while, but no later than the time we expect the next item to come // off the cooldown queue if (checkCooldownQueue && !added) { nextQueueFillRequestStarterQueue = System.currentTimeMillis() + WAIT_AFTER_NOTHING_TO_START; if (nextQueueFillRequestStarterQueue > noLaterThan) nextQueueFillRequestStarterQueue = noLaterThan + 1; } } if (addedMore) starter.wakeUp(); return; } boolean full = addToStarterQueue(request, container); container.deactivate(request, 1); if (!added) starter.wakeUp(); else addedMore = true; added = true; if (full) { if (addedMore) starter.wakeUp(); return; } } } finally { synchronized (this) { fillingRequestStarterQueue = false; } } }
/** * Imports a identity XML file into the given web of trust. This includes: - The identity itself * and its attributes - The trust list of the identity, if it has published one in the XML. * * @param xmlInputStream The input stream containing the XML. */ public void importIdentity(FreenetURI identityURI, InputStream xmlInputStream) { try { // Catch import problems so we can mark the edition as parsing failed // We first parse the XML without synchronization, then do the synchronized import into the // WebOfTrust final ParsedIdentityXML xmlData = parseIdentityXML(xmlInputStream); synchronized (mWoT) { synchronized (mWoT.getIdentityFetcher()) { final Identity identity = mWoT.getIdentityByURI(identityURI); Logger.normal(this, "Importing parsed XML for " + identity); long newEdition = identityURI.getEdition(); if (identity.getEdition() > newEdition) { if (logDEBUG) Logger.debug( this, "Fetched an older edition: current == " + identity.getEdition() + "; fetched == " + identityURI.getEdition()); return; } else if (identity.getEdition() == newEdition) { if (identity.getCurrentEditionFetchState() == FetchState.Fetched) { if (logDEBUG) Logger.debug( this, "Fetched current edition which is marked as fetched already, not importing: " + identityURI); return; } else if (identity.getCurrentEditionFetchState() == FetchState.ParsingFailed) { Logger.normal( this, "Re-fetched current-edition which was marked as parsing failed: " + identityURI); } } // We throw parse errors AFTER checking the edition number: If this XML was outdated // anyway, we don't have to throw. if (xmlData.parseError != null) throw xmlData.parseError; synchronized (Persistent.transactionLock(mDB)) { try { // Transaction rollback block identity.setEdition( newEdition); // The identity constructor only takes the edition number as a hint, // so we must store it explicitly. boolean didPublishTrustListPreviously = identity.doesPublishTrustList(); identity.setPublishTrustList(xmlData.identityPublishesTrustList); try { identity.setNickname(xmlData.identityName); } catch (Exception e) { /* Nickname changes are not allowed, ignore them... */ Logger.warning(this, "setNickname() failed.", e); } try { /* Failure of context importing should not make an identity disappear, therefore we catch exceptions. */ identity.setContexts(xmlData.identityContexts); } catch (Exception e) { Logger.warning(this, "setContexts() failed.", e); } try { /* Failure of property importing should not make an identity disappear, therefore we catch exceptions. */ identity.setProperties(xmlData.identityProperties); } catch (Exception e) { Logger.warning(this, "setProperties() failed", e); } mWoT .beginTrustListImport(); // We delete the old list if !identityPublishesTrustList // and it did publish one earlier => we always call this. if (xmlData.identityPublishesTrustList) { // We import the trust list of an identity if it's score is equal to 0, but we only // create new identities or import edition hints // if the score is greater than 0. Solving a captcha therefore only allows you to // create one single identity. boolean positiveScore = false; boolean hasCapacity = false; // TODO: getBestScore/getBestCapacity should always yield a positive result because // we store a positive score object for an OwnIdentity // upon creation. The only case where it could not exist might be // restoreOwnIdentity() ... check that. If it is created there as well, // remove the additional check here. if (identity instanceof OwnIdentity) { // Importing of OwnIdentities is always allowed positiveScore = true; hasCapacity = true; } else { try { positiveScore = mWoT.getBestScore(identity) > 0; hasCapacity = mWoT.getBestCapacity(identity) > 0; } catch (NotInTrustTreeException e) { } } HashSet<String> identitiesWithUpdatedEditionHint = null; if (positiveScore) { identitiesWithUpdatedEditionHint = new HashSet<String>(xmlData.identityTrustList.size() * 2); } for (final ParsedIdentityXML.TrustListEntry trustListEntry : xmlData.identityTrustList) { final FreenetURI trusteeURI = trustListEntry.mTrusteeURI; final byte trustValue = trustListEntry.mTrustValue; final String trustComment = trustListEntry.mTrustComment; Identity trustee = null; try { trustee = mWoT.getIdentityByURI(trusteeURI); if (positiveScore) { if (trustee.setNewEditionHint(trusteeURI.getEdition())) { identitiesWithUpdatedEditionHint.add(trustee.getID()); trustee.storeWithoutCommit(); } } } catch (UnknownIdentityException e) { if (hasCapacity) { /* We only create trustees if the truster has capacity to rate them. */ try { trustee = new Identity(mWoT, trusteeURI, null, false); trustee.storeWithoutCommit(); } catch (MalformedURLException urlEx) { // Logging the exception does NOT log the actual malformed URL so we do it // manually. Logger.warning( this, "Received malformed identity URL: " + trusteeURI, urlEx); throw urlEx; } } } if (trustee != null) mWoT.setTrustWithoutCommit(identity, trustee, trustValue, trustComment); } for (Trust trust : mWoT.getGivenTrustsOfDifferentEdition(identity, identityURI.getEdition())) { mWoT.removeTrustWithoutCommit(trust); } IdentityFetcher identityFetcher = mWoT.getIdentityFetcher(); if (positiveScore) { for (String id : identitiesWithUpdatedEditionHint) identityFetcher.storeUpdateEditionHintCommandWithoutCommit(id); // We do not have to store fetch commands for new identities here, // setTrustWithoutCommit does it. } } else if (!xmlData.identityPublishesTrustList && didPublishTrustListPreviously && !(identity instanceof OwnIdentity)) { // If it does not publish a trust list anymore, we delete all trust values it has // given. for (Trust trust : mWoT.getGivenTrusts(identity)) mWoT.removeTrustWithoutCommit(trust); } mWoT.finishTrustListImport(); identity.onFetched(); // Marks the identity as parsed successfully identity.storeAndCommit(); } catch (Exception e) { mWoT.abortTrustListImport(e, Logger.LogLevel.WARNING); // Does the rollback throw e; } // try } // synchronized(Persistent.transactionLock(db)) Logger.normal(this, "Finished XML import for " + identity); } // synchronized(mWoT) } // synchronized(mWoT.getIdentityFetcher()) } // try catch (Exception e) { synchronized (mWoT) { synchronized (mWoT.getIdentityFetcher()) { try { final Identity identity = mWoT.getIdentityByURI(identityURI); final long newEdition = identityURI.getEdition(); if (identity.getEdition() <= newEdition) { Logger.normal(this, "Marking edition as parsing failed: " + identityURI); try { identity.setEdition(newEdition); } catch (InvalidParameterException e1) { // Would only happen if newEdition < current edition. // We have validated the opposite. throw new RuntimeException(e1); } identity.onParsingFailed(); identity.storeAndCommit(); } else { Logger.normal( this, "Not marking edition as parsing failed, we have already fetched a new one (" + identity.getEdition() + "):" + identityURI); } Logger.normal(this, "Parsing identity XML failed gracefully for " + identityURI, e); } catch (UnknownIdentityException uie) { Logger.error(this, "Fetched an unknown identity: " + identityURI); } } } } }