import net.pterodactylus.sone.data.Sone.ShowCustomAvatars;
import net.pterodactylus.sone.data.Sone.SoneStatus;
import net.pterodactylus.sone.data.TemporaryImage;
+ import net.pterodactylus.sone.data.impl.PostImpl;
+import net.pterodactylus.sone.database.Database;
import net.pterodactylus.sone.fcp.FcpInterface;
import net.pterodactylus.sone.fcp.FcpInterface.FullAccessRequired;
import net.pterodactylus.sone.freenet.wot.Identity;
* The freenet interface
* @param identityManager
* The identity manager
+ * @param webOfTrustUpdater
+ * The WebOfTrust updater
*/
- public Core(Configuration configuration, Database database, FreenetInterface freenetInterface, IdentityManager identityManager) {
- public Core(Configuration configuration, FreenetInterface freenetInterface, IdentityManager identityManager, WebOfTrustUpdater webOfTrustUpdater) {
++ public Core(Configuration configuration, Database database, FreenetInterface freenetInterface, IdentityManager identityManager, WebOfTrustUpdater webOfTrustUpdater) {
super("Sone Core");
this.configuration = configuration;
+ this.database = database;
this.freenetInterface = freenetInterface;
this.identityManager = identityManager;
this.soneDownloader = new SoneDownloader(this, freenetInterface);
}
/**
- * Retrieves the trust relationship from the origin to the target. If the
- * trust relationship can not be retrieved, {@code null} is returned.
- *
- * @see Identity#getTrust(OwnIdentity)
- * @param origin
- * The origin of the trust tree
- * @param target
- * The target of the trust
- * @return The trust relationship
- */
- public Trust getTrust(Sone origin, Sone target) {
- if (!origin.isLocal()) {
- logger.log(Level.WARNING, String.format("Tried to get trust from remote Sone: %s", origin));
- return null;
- }
- return target.getIdentity().getTrust((OwnIdentity) origin.getIdentity());
- }
-
- /**
-- * Sets the trust value of the given origin Sone for the target Sone.
++ * Sets the trust value of the given origin Sone for
++ * the target Sone.
*
* @param origin
* The origin Sone
logger.log(Level.WARNING, String.format("Tried to delete Sone of non-own identity: %s", sone));
return;
}
- synchronized (localSones) {
- if (!localSones.containsKey(sone.getId())) {
- logger.log(Level.WARNING, String.format("Tried to delete non-local Sone: %s", sone));
- return;
- }
- localSones.remove(sone.getId());
- SoneInserter soneInserter = soneInserters.remove(sone);
- soneInserter.removeSoneInsertListener(this);
- soneInserter.stop();
+ if (!sone.isLocal()) {
+ logger.log(Level.WARNING, String.format("Tried to delete non-local Sone: %s", sone));
+ return;
}
- try {
- ((OwnIdentity) sone.getIdentity()).removeContext("Sone");
- ((OwnIdentity) sone.getIdentity()).removeProperty("Sone.LatestEdition");
- } catch (WebOfTrustException wote1) {
- logger.log(Level.WARNING, String.format("Could not remove context and properties from Sone: %s", sone), wote1);
- }
+ database.removeSone(sone.getId());
+ SoneInserter soneInserter = soneInserters.remove(sone);
+ soneInserter.removeSoneInsertListener(this);
+ soneInserter.stop();
+ webOfTrustUpdater.removeContext((OwnIdentity) sone.getIdentity(), "Sone");
+ webOfTrustUpdater.removeProperty((OwnIdentity) sone.getIdentity(), "Sone.LatestEdition");
try {
configuration.getLongValue("Sone/" + sone.getId() + "/Time").setValue(null);
} catch (ConfigurationException ce1) {
*/
@Override
public void serviceStop() {
- for (SoneInserter soneInserter : soneInserters.values()) {
- soneInserter.removeSoneInsertListener(this);
- soneInserter.stop();
- synchronized (localSones) {
- for (Entry<Sone, SoneInserter> soneInserter : soneInserters.entrySet()) {
- soneInserter.getValue().removeSoneInsertListener(this);
- soneInserter.getValue().stop();
- saveSone(soneInserter.getKey());
- }
++ for (Entry<Sone, SoneInserter> soneInserter : soneInserters.entrySet()) {
++ soneInserter.getValue().removeSoneInsertListener(this);
++ soneInserter.getValue().stop();
++ saveSone(soneInserter.getKey());
}
+ saveConfiguration();
+ webOfTrustUpdater.stop();
updateChecker.stop();
updateChecker.removeUpdateListener(this);
soneDownloader.stop();
--- /dev/null
- albums.add(album);
+/*
+ * Sone - MemorySone.java - Copyright © 2010–2012 David Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.database.memory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import net.pterodactylus.sone.core.Options;
+import net.pterodactylus.sone.data.Album;
+import net.pterodactylus.sone.data.Client;
+import net.pterodactylus.sone.data.Image;
+import net.pterodactylus.sone.data.Post;
+import net.pterodactylus.sone.data.PostReply;
+import net.pterodactylus.sone.data.Profile;
+import net.pterodactylus.sone.data.Reply;
+import net.pterodactylus.sone.data.Sone;
+import net.pterodactylus.sone.database.Database;
+import net.pterodactylus.sone.freenet.wot.Identity;
+import net.pterodactylus.util.logging.Logging;
+import net.pterodactylus.util.validation.Validation;
+import freenet.keys.FreenetURI;
+
+/**
+ * Implementation of a {@link Sone} that keeps all added data in memory. A
+ * self-created instance of this class should be converted to a {@link Database}
+ * -based instance of {@link Sone} as soon as possible (unless it was returned
+ * by a {@link MemoryDatabase}).
+ *
+ * @author <a href="mailto:bombe@pterodactylus.net">David ‘Bombe’ Roden</a>
+ */
+public class MemorySone implements Sone {
+
+ /** The logger. */
+ private static final Logger logger = Logging.getLogger(Sone.class);
+
+ /** The ID of this Sone. */
+ private final String id;
+
+ /** Whether this is a local Sone. */
+ private final boolean local;
+
+ /** The identity of this Sone. */
+ private Identity identity;
+
+ /** The URI under which the Sone is stored in Freenet. */
+ private volatile FreenetURI requestUri;
+
+ /** The URI used to insert a new version of this Sone. */
+ /* This will be null for remote Sones! */
+ private volatile FreenetURI insertUri;
+
+ /** The latest edition of the Sone. */
+ private volatile long latestEdition;
+
+ /** The time of the last inserted update. */
+ private volatile long time;
+
+ /** The status of this Sone. */
+ private volatile SoneStatus status = SoneStatus.unknown;
+
+ /** The profile of this Sone. */
+ private volatile Profile profile = new Profile(this);
+
+ /** The client used by the Sone. */
+ private volatile Client client;
+
+ /** Whether this Sone is known. */
+ private volatile boolean known;
+
+ /** All friend Sones. */
+ private final Set<String> friendSones = new CopyOnWriteArraySet<String>();
+
+ /** All posts. */
+ private final Set<Post> posts = new CopyOnWriteArraySet<Post>();
+
+ /** All replies. */
+ private final Set<PostReply> replies = new CopyOnWriteArraySet<PostReply>();
+
+ /** The IDs of all liked posts. */
+ private final Set<String> likedPostIds = new CopyOnWriteArraySet<String>();
+
+ /** The IDs of all liked replies. */
+ private final Set<String> likedReplyIds = new CopyOnWriteArraySet<String>();
+
+ /** The albums of this Sone. */
+ private final List<Album> albums = new CopyOnWriteArrayList<Album>();
+
+ /** Sone-specific options. */
+ private final Options options = new Options();
+
+ /**
+ * Creates a new Sone.
+ *
+ * @param id
+ * The ID of the Sone
+ * @param local
+ * {@code true} if this Sone is local, {@code false} otherwise
+ */
+ public MemorySone(String id, boolean local) {
+ this.id = id;
+ this.local = local;
+ }
+
+ //
+ // ACCESSORS
+ //
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Identity getIdentity() {
+ return identity;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone setIdentity(Identity identity) throws IllegalArgumentException {
+ if (!identity.getId().equals(id)) {
+ throw new IllegalArgumentException("Identity’s ID does not match Sone’s ID!");
+ }
+ this.identity = identity;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isLocal() {
+ return local;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getName() {
+ return (identity != null) ? identity.getNickname() : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public FreenetURI getRequestUri() {
+ return (requestUri != null) ? requestUri.setSuggestedEdition(latestEdition) : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone setRequestUri(FreenetURI requestUri) {
+ if (this.requestUri == null) {
+ this.requestUri = requestUri.setKeyType("USK").setDocName("Sone").setMetaString(new String[0]);
+ return this;
+ }
+ if (!this.requestUri.equalsKeypair(requestUri)) {
+ logger.log(Level.WARNING, String.format("Request URI %s tried to overwrite %s!", requestUri, this.requestUri));
+ return this;
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public FreenetURI getInsertUri() {
+ return (insertUri != null) ? insertUri.setSuggestedEdition(latestEdition) : null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone setInsertUri(FreenetURI insertUri) {
+ if (this.insertUri == null) {
+ this.insertUri = insertUri.setKeyType("USK").setDocName("Sone").setMetaString(new String[0]);
+ return this;
+ }
+ if (!this.insertUri.equalsKeypair(insertUri)) {
+ logger.log(Level.WARNING, String.format("Request URI %s tried to overwrite %s!", insertUri, this.insertUri));
+ return this;
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long getLatestEdition() {
+ return latestEdition;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setLatestEdition(long latestEdition) {
+ if (!(latestEdition > this.latestEdition)) {
+ logger.log(Level.FINE, String.format("New latest edition %d is not greater than current latest edition %d!", latestEdition, this.latestEdition));
+ return;
+ }
+ this.latestEdition = latestEdition;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long getTime() {
+ return time;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone setTime(long time) {
+ this.time = time;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SoneStatus getStatus() {
+ return status;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone setStatus(SoneStatus status) {
+ Validation.begin().isNotNull("Sone Status", status).check();
+ this.status = status;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Profile getProfile() {
+ return new Profile(profile);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setProfile(Profile profile) {
+ this.profile = new Profile(profile);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Client getClient() {
+ return client;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone setClient(Client client) {
+ this.client = client;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isKnown() {
+ return known;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone setKnown(boolean known) {
+ this.known = known;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<String> getFriends() {
+ List<String> friends = new ArrayList<String>(friendSones);
+ return friends;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean hasFriend(String friendSoneId) {
+ return friendSones.contains(friendSoneId);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone addFriend(String friendSone) {
+ if (!friendSone.equals(id)) {
+ friendSones.add(friendSone);
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone removeFriend(String friendSoneId) {
+ friendSones.remove(friendSoneId);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<Post> getPosts() {
+ List<Post> sortedPosts;
+ synchronized (this) {
+ sortedPosts = new ArrayList<Post>(posts);
+ }
+ Collections.sort(sortedPosts, Post.TIME_COMPARATOR);
+ return sortedPosts;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone setPosts(Collection<Post> posts) {
+ synchronized (this) {
+ this.posts.clear();
+ this.posts.addAll(posts);
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addPost(Post post) {
+ if (post.getSone().equals(this) && posts.add(post)) {
+ logger.log(Level.FINEST, String.format("Adding %s to “%s”.", post, getName()));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removePost(Post post) {
+ if (post.getSone().equals(this)) {
+ posts.remove(post);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<PostReply> getReplies() {
+ return Collections.unmodifiableSet(replies);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone setReplies(Collection<PostReply> replies) {
+ this.replies.clear();
+ this.replies.addAll(replies);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addReply(PostReply reply) {
+ if (reply.getSone().equals(this)) {
+ replies.add(reply);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeReply(PostReply reply) {
+ if (reply.getSone().equals(this)) {
+ replies.remove(reply);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<String> getLikedPostIds() {
+ return Collections.unmodifiableSet(likedPostIds);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone setLikePostIds(Set<String> likedPostIds) {
+ this.likedPostIds.clear();
+ this.likedPostIds.addAll(likedPostIds);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isLikedPostId(String postId) {
+ return likedPostIds.contains(postId);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone addLikedPostId(String postId) {
+ likedPostIds.add(postId);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone removeLikedPostId(String postId) {
+ likedPostIds.remove(postId);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<String> getLikedReplyIds() {
+ return Collections.unmodifiableSet(likedReplyIds);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone setLikeReplyIds(Set<String> likedReplyIds) {
+ this.likedReplyIds.clear();
+ this.likedReplyIds.addAll(likedReplyIds);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isLikedReplyId(String replyId) {
+ return likedReplyIds.contains(replyId);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone addLikedReplyId(String replyId) {
+ likedReplyIds.add(replyId);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Sone removeLikedReplyId(String replyId) {
+ likedReplyIds.remove(replyId);
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<Album> getAlbums() {
+ return Collections.unmodifiableList(albums);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<Album> getAllAlbums() {
+ List<Album> flatAlbums = new ArrayList<Album>();
+ flatAlbums.addAll(albums);
+ int lastAlbumIndex = 0;
+ while (lastAlbumIndex < flatAlbums.size()) {
+ int previousAlbumCount = flatAlbums.size();
+ for (Album album : new ArrayList<Album>(flatAlbums.subList(lastAlbumIndex, flatAlbums.size()))) {
+ flatAlbums.addAll(album.getAlbums());
+ }
+ lastAlbumIndex = previousAlbumCount;
+ }
+ return flatAlbums;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<Image> getAllImages() {
+ List<Image> allImages = new ArrayList<Image>();
+ for (Album album : getAllAlbums()) {
+ allImages.addAll(album.getImages());
+ }
+ return allImages;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addAlbum(Album album) {
+ Validation.begin().isNotNull("Album", album).check().isEqual("Album Owner", album.getSone(), this).check();
++ if (!albums.contains(album)) {
++ albums.add(album);
++ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setAlbums(Collection<? extends Album> albums) {
+ Validation.begin().isNotNull("Albums", albums).check();
+ this.albums.clear();
+ for (Album album : albums) {
+ addAlbum(album);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeAlbum(Album album) {
+ Validation.begin().isNotNull("Album", album).check().isEqual("Album Owner", album.getSone(), this).check();
+ albums.remove(album);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Album moveAlbumUp(Album album) {
+ Validation.begin().isNotNull("Album", album).check().isEqual("Album Owner", album.getSone(), this).isNull("Album Parent", album.getParent()).check();
+ int oldIndex = albums.indexOf(album);
+ if (oldIndex <= 0) {
+ return null;
+ }
+ albums.remove(oldIndex);
+ albums.add(oldIndex - 1, album);
+ return albums.get(oldIndex);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Album moveAlbumDown(Album album) {
+ Validation.begin().isNotNull("Album", album).check().isEqual("Album Owner", album.getSone(), this).isNull("Album Parent", album.getParent()).check();
+ int oldIndex = albums.indexOf(album);
+ if ((oldIndex < 0) || (oldIndex >= (albums.size() - 1))) {
+ return null;
+ }
+ albums.remove(oldIndex);
+ albums.add(oldIndex + 1, album);
+ return albums.get(oldIndex);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Options getOptions() {
+ return options;
+ }
+
+ //
+ // FINGERPRINTABLE METHODS
+ //
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized String getFingerprint() {
+ StringBuilder fingerprint = new StringBuilder();
+ fingerprint.append(profile.getFingerprint());
+
+ fingerprint.append("Posts(");
+ for (Post post : getPosts()) {
+ fingerprint.append("Post(").append(post.getId()).append(')');
+ }
+ fingerprint.append(")");
+
+ List<PostReply> replies = new ArrayList<PostReply>(getReplies());
+ Collections.sort(replies, Reply.TIME_COMPARATOR);
+ fingerprint.append("Replies(");
+ for (PostReply reply : replies) {
+ fingerprint.append("Reply(").append(reply.getId()).append(')');
+ }
+ fingerprint.append(')');
+
+ List<String> likedPostIds = new ArrayList<String>(getLikedPostIds());
+ Collections.sort(likedPostIds);
+ fingerprint.append("LikedPosts(");
+ for (String likedPostId : likedPostIds) {
+ fingerprint.append("Post(").append(likedPostId).append(')');
+ }
+ fingerprint.append(')');
+
+ List<String> likedReplyIds = new ArrayList<String>(getLikedReplyIds());
+ Collections.sort(likedReplyIds);
+ fingerprint.append("LikedReplies(");
+ for (String likedReplyId : likedReplyIds) {
+ fingerprint.append("Reply(").append(likedReplyId).append(')');
+ }
+ fingerprint.append(')');
+
+ fingerprint.append("Albums(");
+ for (Album album : albums) {
+ fingerprint.append(album.getFingerprint());
+ }
+ fingerprint.append(')');
+
+ return fingerprint.toString();
+ }
+
+ //
+ // INTERFACE Comparable<Sone>
+ //
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(Sone sone) {
+ return NICE_NAME_COMPARATOR.compare(this, sone);
+ }
+
+ //
+ // OBJECT METHODS
+ //
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ return id.hashCode();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object object) {
+ if (!(object instanceof Sone)) {
+ return false;
+ }
+ return ((Sone) object).getId().equals(id);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return getClass().getName() + "[identity=" + identity + ",requestUri=" + requestUri + ",insertUri(" + String.valueOf(insertUri).length() + "),friends(" + friendSones.size() + "),posts(" + posts.size() + "),replies(" + replies.size() + ")]";
+ }
+
+}
import net.pterodactylus.sone.core.Core;
import net.pterodactylus.sone.core.FreenetInterface;
+ import net.pterodactylus.sone.core.WebOfTrustUpdater;
+import net.pterodactylus.sone.database.Database;
+import net.pterodactylus.sone.database.memory.MemoryDatabase;
import net.pterodactylus.sone.fcp.FcpInterface;
import net.pterodactylus.sone.freenet.PluginStoreConfigurationBackend;
import net.pterodactylus.sone.freenet.plugin.PluginConnector;
identityManager = new IdentityManager(webOfTrustConnector);
identityManager.setContext("Sone");
+ /* create Sone database. */
+ Database soneDatabase = new MemoryDatabase();
+
+ /* create trust updater. */
+ WebOfTrustUpdater trustUpdater = new WebOfTrustUpdater(webOfTrustConnector);
+ trustUpdater.init();
+
/* create core. */
- core = new Core(oldConfiguration, soneDatabase, freenetInterface, identityManager);
- core = new Core(oldConfiguration, freenetInterface, identityManager, trustUpdater);
++ core = new Core(oldConfiguration, soneDatabase, freenetInterface, identityManager, trustUpdater);
/* create the web interface. */
webInterface = new WebInterface(this);
import net.pterodactylus.sone.core.SoneProvider;
import net.pterodactylus.sone.data.Post;
import net.pterodactylus.sone.data.Sone;
+import net.pterodactylus.sone.database.memory.MemorySone;
+ import net.pterodactylus.util.io.Closer;
import net.pterodactylus.util.logging.Logging;
import freenet.keys.FreenetURI;
public Iterable<Part> parse(SoneTextParserContext context, Reader source) throws IOException {
PartContainer parts = new PartContainer();
BufferedReader bufferedReader = (source instanceof BufferedReader) ? (BufferedReader) source : new BufferedReader(source);
- String line;
- boolean lastLineEmpty = true;
- int emptyLines = 0;
- while ((line = bufferedReader.readLine()) != null) {
- if (line.trim().length() == 0) {
- if (lastLineEmpty) {
+ try {
+ String line;
+ boolean lastLineEmpty = true;
+ int emptyLines = 0;
+ while ((line = bufferedReader.readLine()) != null) {
+ if (line.trim().length() == 0) {
+ if (lastLineEmpty) {
+ continue;
+ }
+ parts.add(new PlainTextPart("\n"));
+ ++emptyLines;
+ lastLineEmpty = emptyLines == 2;
continue;
}
- parts.add(new PlainTextPart("\n"));
- ++emptyLines;
- lastLineEmpty = emptyLines == 2;
- continue;
- }
- emptyLines = 0;
- /*
- * lineComplete tracks whether the block you are parsing is the
- * first block of the line. this is important because sometimes you
- * have to add an additional line break.
- */
- boolean lineComplete = true;
- while (line.length() > 0) {
- int nextKsk = line.indexOf("KSK@");
- int nextChk = line.indexOf("CHK@");
- int nextSsk = line.indexOf("SSK@");
- int nextUsk = line.indexOf("USK@");
- int nextHttp = line.indexOf("http://");
- int nextHttps = line.indexOf("https://");
- int nextSone = line.indexOf("sone://");
- int nextPost = line.indexOf("post://");
- if ((nextKsk == -1) && (nextChk == -1) && (nextSsk == -1) && (nextUsk == -1) && (nextHttp == -1) && (nextHttps == -1) && (nextSone == -1) && (nextPost == -1)) {
- if (lineComplete && !lastLineEmpty) {
- parts.add(new PlainTextPart("\n" + line));
- } else {
- parts.add(new PlainTextPart(line));
+ emptyLines = 0;
+ /*
+ * lineComplete tracks whether the block you are parsing is the
+ * first block of the line. this is important because sometimes
+ * you have to add an additional line break.
+ */
+ boolean lineComplete = true;
+ while (line.length() > 0) {
+ int nextKsk = line.indexOf("KSK@");
+ int nextChk = line.indexOf("CHK@");
+ int nextSsk = line.indexOf("SSK@");
+ int nextUsk = line.indexOf("USK@");
+ int nextHttp = line.indexOf("http://");
+ int nextHttps = line.indexOf("https://");
+ int nextSone = line.indexOf("sone://");
+ int nextPost = line.indexOf("post://");
+ if ((nextKsk == -1) && (nextChk == -1) && (nextSsk == -1) && (nextUsk == -1) && (nextHttp == -1) && (nextHttps == -1) && (nextSone == -1) && (nextPost == -1)) {
+ if (lineComplete && !lastLineEmpty) {
+ parts.add(new PlainTextPart("\n" + line));
+ } else {
+ parts.add(new PlainTextPart(line));
+ }
+ break;
+ }
+ int next = Integer.MAX_VALUE;
+ LinkType linkType = null;
+ if ((nextKsk > -1) && (nextKsk < next)) {
+ next = nextKsk;
+ linkType = LinkType.KSK;
+ }
+ if ((nextChk > -1) && (nextChk < next)) {
+ next = nextChk;
+ linkType = LinkType.CHK;
+ }
+ if ((nextSsk > -1) && (nextSsk < next)) {
+ next = nextSsk;
+ linkType = LinkType.SSK;
+ }
+ if ((nextUsk > -1) && (nextUsk < next)) {
+ next = nextUsk;
+ linkType = LinkType.USK;
+ }
+ if ((nextHttp > -1) && (nextHttp < next)) {
+ next = nextHttp;
+ linkType = LinkType.HTTP;
+ }
+ if ((nextHttps > -1) && (nextHttps < next)) {
+ next = nextHttps;
+ linkType = LinkType.HTTPS;
+ }
+ if ((nextSone > -1) && (nextSone < next)) {
+ next = nextSone;
+ linkType = LinkType.SONE;
+ }
+ if ((nextPost > -1) && (nextPost < next)) {
+ next = nextPost;
+ linkType = LinkType.POST;
}
- break;
- }
- int next = Integer.MAX_VALUE;
- LinkType linkType = null;
- if ((nextKsk > -1) && (nextKsk < next)) {
- next = nextKsk;
- linkType = LinkType.KSK;
- }
- if ((nextChk > -1) && (nextChk < next)) {
- next = nextChk;
- linkType = LinkType.CHK;
- }
- if ((nextSsk > -1) && (nextSsk < next)) {
- next = nextSsk;
- linkType = LinkType.SSK;
- }
- if ((nextUsk > -1) && (nextUsk < next)) {
- next = nextUsk;
- linkType = LinkType.USK;
- }
- if ((nextHttp > -1) && (nextHttp < next)) {
- next = nextHttp;
- linkType = LinkType.HTTP;
- }
- if ((nextHttps > -1) && (nextHttps < next)) {
- next = nextHttps;
- linkType = LinkType.HTTPS;
- }
- if ((nextSone > -1) && (nextSone < next)) {
- next = nextSone;
- linkType = LinkType.SONE;
- }
- if ((nextPost > -1) && (nextPost < next)) {
- next = nextPost;
- linkType = LinkType.POST;
- }
- /* cut off “freenet:” from before keys. */
- if (((linkType == LinkType.KSK) || (linkType == LinkType.CHK) || (linkType == LinkType.SSK) || (linkType == LinkType.USK)) && (next >= 8) && (line.substring(next - 8, next).equals("freenet:"))) {
- next -= 8;
- line = line.substring(0, next) + line.substring(next + 8);
- }
+ /* cut off “freenet:” from before keys. */
+ if (((linkType == LinkType.KSK) || (linkType == LinkType.CHK) || (linkType == LinkType.SSK) || (linkType == LinkType.USK)) && (next >= 8) && (line.substring(next - 8, next).equals("freenet:"))) {
+ next -= 8;
+ line = line.substring(0, next) + line.substring(next + 8);
+ }
- /* if there is text before the next item, write it out. */
- if (lineComplete && !lastLineEmpty) {
- parts.add(new PlainTextPart("\n"));
- }
- if (next > 0) {
- parts.add(new PlainTextPart(line.substring(0, next)));
- line = line.substring(next);
- next = 0;
- }
- lineComplete = false;
+ /* if there is text before the next item, write it out. */
+ if (lineComplete && !lastLineEmpty) {
+ parts.add(new PlainTextPart("\n"));
+ }
+ if (next > 0) {
+ parts.add(new PlainTextPart(line.substring(0, next)));
+ line = line.substring(next);
+ next = 0;
+ }
+ lineComplete = false;
- if (linkType == LinkType.SONE) {
- if (line.length() >= (7 + 43)) {
- String soneId = line.substring(7, 50);
- Sone sone = soneProvider.getSone(soneId, false);
- if (sone == null) {
- /*
- * don’t use create=true above, we don’t want the
- * empty shell.
- */
- sone = new MemorySone(soneId, false);
+ if (linkType == LinkType.SONE) {
+ if (line.length() >= (7 + 43)) {
+ String soneId = line.substring(7, 50);
+ Sone sone = soneProvider.getSone(soneId, false);
+ if (sone == null) {
+ /*
+ * don’t use create=true above, we don’t want
+ * the empty shell.
+ */
- sone = new Sone(soneId);
++ sone = new MemorySone(soneId, false);
+ }
+ parts.add(new SonePart(sone));
+ line = line.substring(50);
+ } else {
+ parts.add(new PlainTextPart(line));
+ line = "";
}
- parts.add(new SonePart(sone));
- line = line.substring(50);
- } else {
- parts.add(new PlainTextPart(line));
- line = "";
+ continue;
}
- continue;
- }
- if (linkType == LinkType.POST) {
- if (line.length() >= (7 + 36)) {
- String postId = line.substring(7, 43);
- Post post = postProvider.getPost(postId, false);
- if ((post != null) && (post.getSone() != null)) {
- parts.add(new PostPart(post));
+ if (linkType == LinkType.POST) {
+ if (line.length() >= (7 + 36)) {
+ String postId = line.substring(7, 43);
+ Post post = postProvider.getPost(postId, false);
+ if ((post != null) && (post.getSone() != null)) {
+ parts.add(new PostPart(post));
+ } else {
+ parts.add(new PlainTextPart(line.substring(0, 43)));
+ }
+ line = line.substring(43);
} else {
- parts.add(new PlainTextPart(line.substring(0, 43)));
+ parts.add(new PlainTextPart(line));
+ line = "";
}
- line = line.substring(43);
- } else {
- parts.add(new PlainTextPart(line));
- line = "";
+ continue;
}
- continue;
- }
- Matcher matcher = whitespacePattern.matcher(line);
- int nextSpace = matcher.find(0) ? matcher.start() : line.length();
- String link = line.substring(0, nextSpace);
- String name = link;
- logger.log(Level.FINER, String.format("Found link: %s", link));
- logger.log(Level.FINEST, String.format("CHK: %d, SSK: %d, USK: %d", nextChk, nextSsk, nextUsk));
+ Matcher matcher = whitespacePattern.matcher(line);
+ int nextSpace = matcher.find(0) ? matcher.start() : line.length();
+ String link = line.substring(0, nextSpace);
+ String name = link;
+ logger.log(Level.FINER, String.format("Found link: %s", link));
+ logger.log(Level.FINEST, String.format("CHK: %d, SSK: %d, USK: %d", nextChk, nextSsk, nextUsk));
- if ((linkType == LinkType.KSK) || (linkType == LinkType.CHK) || (linkType == LinkType.SSK) || (linkType == LinkType.USK)) {
- FreenetURI uri;
- if (name.indexOf('?') > -1) {
- name = name.substring(0, name.indexOf('?'));
- }
- if (name.endsWith("/")) {
- name = name.substring(0, name.length() - 1);
- }
- try {
- uri = new FreenetURI(name);
- name = uri.lastMetaString();
- if (name == null) {
- name = uri.getDocName();
+ if ((linkType == LinkType.KSK) || (linkType == LinkType.CHK) || (linkType == LinkType.SSK) || (linkType == LinkType.USK)) {
+ FreenetURI uri;
+ if (name.indexOf('?') > -1) {
+ name = name.substring(0, name.indexOf('?'));
}
- if (name == null) {
- name = link.substring(0, Math.min(9, link.length()));
+ if (name.endsWith("/")) {
+ name = name.substring(0, name.length() - 1);
}
- boolean fromPostingSone = ((linkType == LinkType.SSK) || (linkType == LinkType.USK)) && (context != null) && (context.getPostingSone() != null) && link.substring(4, Math.min(link.length(), 47)).equals(context.getPostingSone().getId());
- parts.add(new FreenetLinkPart(link, name, fromPostingSone));
- } catch (MalformedURLException mue1) {
- /* not a valid link, insert as plain text. */
- parts.add(new PlainTextPart(link));
- } catch (NullPointerException npe1) {
- /* FreenetURI sometimes throws these, too. */
- parts.add(new PlainTextPart(link));
- } catch (ArrayIndexOutOfBoundsException aioobe1) {
- /* oh, and these, too. */
- parts.add(new PlainTextPart(link));
- }
- } else if ((linkType == LinkType.HTTP) || (linkType == LinkType.HTTPS)) {
- name = link.substring(linkType == LinkType.HTTP ? 7 : 8);
- int firstSlash = name.indexOf('/');
- int lastSlash = name.lastIndexOf('/');
- if ((lastSlash - firstSlash) > 3) {
- name = name.substring(0, firstSlash + 1) + "…" + name.substring(lastSlash);
- }
- if (name.endsWith("/")) {
- name = name.substring(0, name.length() - 1);
- }
- if (((name.indexOf('/') > -1) && (name.indexOf('.') < name.lastIndexOf('.', name.indexOf('/'))) || ((name.indexOf('/') == -1) && (name.indexOf('.') < name.lastIndexOf('.')))) && name.startsWith("www.")) {
- name = name.substring(4);
- }
- if (name.indexOf('?') > -1) {
- name = name.substring(0, name.indexOf('?'));
+ try {
+ uri = new FreenetURI(name);
+ name = uri.lastMetaString();
+ if (name == null) {
+ name = uri.getDocName();
+ }
+ if (name == null) {
+ name = link.substring(0, Math.min(9, link.length()));
+ }
+ boolean fromPostingSone = ((linkType == LinkType.SSK) || (linkType == LinkType.USK)) && (context != null) && (context.getPostingSone() != null) && link.substring(4, Math.min(link.length(), 47)).equals(context.getPostingSone().getId());
+ parts.add(new FreenetLinkPart(link, name, fromPostingSone));
+ } catch (MalformedURLException mue1) {
+ /* not a valid link, insert as plain text. */
+ parts.add(new PlainTextPart(link));
+ } catch (NullPointerException npe1) {
+ /* FreenetURI sometimes throws these, too. */
+ parts.add(new PlainTextPart(link));
+ } catch (ArrayIndexOutOfBoundsException aioobe1) {
+ /* oh, and these, too. */
+ parts.add(new PlainTextPart(link));
+ }
+ } else if ((linkType == LinkType.HTTP) || (linkType == LinkType.HTTPS)) {
+ name = link.substring(linkType == LinkType.HTTP ? 7 : 8);
+ int firstSlash = name.indexOf('/');
+ int lastSlash = name.lastIndexOf('/');
+ if ((lastSlash - firstSlash) > 3) {
+ name = name.substring(0, firstSlash + 1) + "…" + name.substring(lastSlash);
+ }
+ if (name.endsWith("/")) {
+ name = name.substring(0, name.length() - 1);
+ }
+ if (((name.indexOf('/') > -1) && (name.indexOf('.') < name.lastIndexOf('.', name.indexOf('/'))) || ((name.indexOf('/') == -1) && (name.indexOf('.') < name.lastIndexOf('.')))) && name.startsWith("www.")) {
+ name = name.substring(4);
+ }
+ if (name.indexOf('?') > -1) {
+ name = name.substring(0, name.indexOf('?'));
+ }
+ parts.add(new LinkPart(link, name));
}
- parts.add(new LinkPart(link, name));
+ line = line.substring(nextSpace);
}
- line = line.substring(nextSpace);
+ lastLineEmpty = false;
+ }
+ } finally {
+ if (bufferedReader != source) {
+ Closer.close(bufferedReader);
}
- lastLineEmpty = false;
}
for (int partIndex = parts.size() - 1; partIndex >= 0; --partIndex) {
Part part = parts.getPart(partIndex);