+ * Replaces the peer note for the given peer.
+ *
+ * @param peer
+ * The peer
+ * @param noteText
+ * The new base64-encoded note text
+ * @param noteType
+ * The type of the note (currently only <code>1</code> is
+ * allowed)
+ * @throws IOException
+ * if an I/O error occurs
+ * @throws FcpException
+ * if an FCP error occurs
+ */
+ public void modifyPeerNote(final Peer peer, final String noteText, final int noteType) throws IOException, FcpException {
+ new ExtendedFcpAdapter() {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @SuppressWarnings("synthetic-access")
+ public void run() throws IOException {
+ fcpConnection.sendMessage(new ModifyPeerNote(peer.getIdentity(), noteText, noteType));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void receivedPeer(FcpConnection fcpConnection, Peer receivedPeer) {
+ if (receivedPeer.getIdentity().equals(peer.getIdentity())) {
+ completionLatch.countDown();
+ }
+ }
+ }.execute();
+ }
+
+ //
+ // KEY GENERATION
+ //
+
+ /**
+ * Generates a new SSK key pair.
+ *
+ * @return The generated key pair
+ * @throws IOException
+ * if an I/O error occurs
+ * @throws FcpException
+ * if an FCP error occurs
+ */
+ public SSKKeypair generateKeyPair() throws IOException, FcpException {
+ final ObjectWrapper<SSKKeypair> sskKeypairWrapper = new ObjectWrapper<SSKKeypair>();
+ new ExtendedFcpAdapter() {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @SuppressWarnings("synthetic-access")
+ public void run() throws IOException {
+ fcpConnection.sendMessage(new GenerateSSK());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void receivedSSKKeypair(FcpConnection fcpConnection, SSKKeypair sskKeypair) {
+ sskKeypairWrapper.set(sskKeypair);
+ completionLatch.countDown();
+ }
+ }.execute();
+ return sskKeypairWrapper.get();
+ }
+
+ //
+ // REQUEST MANAGEMENT
+ //
+
+ /**
+ * Returns all currently visible persistent get requests.
+ *
+ * @param global
+ * <code>true</code> to return get requests from the global
+ * queue, <code>false</code> to only show requests from the
+ * client-local queue
+ * @return All get requests
+ * @throws IOException
+ * if an I/O error occurs
+ * @throws FcpException
+ * if an FCP error occurs
+ */
+ public Set<PersistentGet> getGetRequests(final boolean global) throws IOException, FcpException {
+ final Set<PersistentGet> getRequests = Collections.synchronizedSet(new HashSet<PersistentGet>());
+ new ExtendedFcpAdapter() {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ @SuppressWarnings("synthetic-access")
+ public void run() throws IOException {
+ fcpConnection.sendMessage(new WatchGlobal(global));
+ fcpConnection.sendMessage(new ListPersistentRequests());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void receivedPersistentGet(FcpConnection fcpConnection, PersistentGet persistentGet) {
+ getRequests.add(persistentGet);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void receivedEndListPersistentRequests(FcpConnection fcpConnection, EndListPersistentRequests endListPersistentRequests) {
+ completionLatch.countDown();
+ }
+ }.execute();
+ return getRequests;
+ }
+
+ //
+ // PRIVATE METHODS
+ //
+
+ /**
+ * Creates a unique request identifier.
+ *
+ * @param basename
+ * The basename of the request
+ * @return The created request identifier
+ */
+ private String createIdentifier(String basename) {
+ return basename + "-" + System.currentTimeMillis() + "-" + (int) (Math.random() * Integer.MAX_VALUE);
+ }
+
+ /**