Merge branch 'next' into feature/album-and-image-links
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Mon, 27 Jul 2015 18:30:21 +0000 (20:30 +0200)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Mon, 27 Jul 2015 18:30:21 +0000 (20:30 +0200)
1  2 
src/main/java/net/pterodactylus/sone/core/SoneParser.java
src/main/java/net/pterodactylus/sone/web/WebInterface.java

@@@ -29,7 -29,6 +29,7 @@@ import net.pterodactylus.sone.database.
  import net.pterodactylus.util.xml.SimpleXML;
  import net.pterodactylus.util.xml.XML;
  
 +import com.google.common.base.Optional;
  import org.w3c.dom.Document;
  
  /**
@@@ -267,10 -266,10 +267,10 @@@ public class SoneParser 
                                        logger.log(Level.WARNING, String.format("Downloaded Sone %s contains invalid album!", sone));
                                        return null;
                                }
 -                              Album parent = null;
 +                              Optional<Album> parent = Optional.absent();
                                if (parentId != null) {
                                        parent = core.getAlbum(parentId);
 -                                      if (parent == null) {
 +                                      if (!parent.isPresent()) {
                                                logger.log(Level.WARNING, String.format("Downloaded Sone %s has album with invalid parent!", sone));
                                                return null;
                                        }
                                                .setTitle(title)
                                                .setDescription(description)
                                                .update();
 -                              if (parent != null) {
 -                                      parent.addAlbum(album);
 +                              if (parent.isPresent()) {
 +                                      parent.get().addAlbum(album);
                                } else {
                                        topLevelAlbums.add(album);
                                }
                }
  
                /* okay, apparently everything was parsed correctly. Now import. */
-               /* atomic setter operation on the Sone. */
-               synchronized (sone) {
-                       sone.setProfile(profile);
-                       sone.setPosts(posts);
-                       sone.setReplies(replies);
-                       sone.setLikePostIds(likedPostIds);
-                       sone.setLikeReplyIds(likedReplyIds);
-                       for (Album album : topLevelAlbums) {
-                               sone.getRootAlbum().addAlbum(album);
-                       }
+               sone.setProfile(profile);
+               sone.setPosts(posts);
+               sone.setReplies(replies);
+               sone.setLikePostIds(likedPostIds);
+               sone.setLikeReplyIds(likedReplyIds);
+               for (Album album : topLevelAlbums) {
+                       sone.getRootAlbum().addAlbum(album);
                }
  
                return sone;
@@@ -21,11 -21,7 +21,7 @@@ import static java.util.logging.Logger.
  import static net.pterodactylus.util.template.TemplateParser.parse;
  
  import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.Reader;
  import java.io.StringReader;
- import java.io.UnsupportedEncodingException;
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Collections;
@@@ -72,11 -68,11 +68,12 @@@ import net.pterodactylus.sone.data.Sone
  import net.pterodactylus.sone.freenet.L10nFilter;
  import net.pterodactylus.sone.freenet.wot.Identity;
  import net.pterodactylus.sone.freenet.wot.Trust;
+ import net.pterodactylus.sone.main.Loaders;
  import net.pterodactylus.sone.main.ReparseFilter;
  import net.pterodactylus.sone.main.SonePlugin;
  import net.pterodactylus.sone.notify.ListNotification;
  import net.pterodactylus.sone.template.AlbumAccessor;
 +import net.pterodactylus.sone.template.BuildIdFilter;
  import net.pterodactylus.sone.template.CollectionAccessor;
  import net.pterodactylus.sone.template.CssClassNameFilter;
  import net.pterodactylus.sone.template.HttpRequestAccessor;
@@@ -87,7 -83,6 +84,7 @@@ import net.pterodactylus.sone.template.
  import net.pterodactylus.sone.template.ParserFilter;
  import net.pterodactylus.sone.template.PostAccessor;
  import net.pterodactylus.sone.template.ProfileAccessor;
 +import net.pterodactylus.sone.template.RenderFilter;
  import net.pterodactylus.sone.template.ReplyAccessor;
  import net.pterodactylus.sone.template.ReplyGroupFilter;
  import net.pterodactylus.sone.template.RequestChangeFilter;
@@@ -131,11 -126,9 +128,9 @@@ import net.pterodactylus.sone.web.ajax.
  import net.pterodactylus.sone.web.page.FreenetRequest;
  import net.pterodactylus.sone.web.page.PageToadlet;
  import net.pterodactylus.sone.web.page.PageToadletFactory;
- import net.pterodactylus.util.io.Closer;
  import net.pterodactylus.util.notify.Notification;
  import net.pterodactylus.util.notify.NotificationManager;
  import net.pterodactylus.util.notify.TemplateNotification;
- import net.pterodactylus.util.template.ClassPathTemplateProvider;
  import net.pterodactylus.util.template.CollectionSortFilter;
  import net.pterodactylus.util.template.ContainsFilter;
  import net.pterodactylus.util.template.DateFilter;
@@@ -152,7 -145,6 +147,6 @@@ import net.pterodactylus.util.template.
  import net.pterodactylus.util.template.TemplateProvider;
  import net.pterodactylus.util.template.XmlFilter;
  import net.pterodactylus.util.web.RedirectPage;
- import net.pterodactylus.util.web.StaticPage;
  import net.pterodactylus.util.web.TemplatePage;
  
  import com.google.common.collect.Collections2;
@@@ -178,6 -170,9 +172,9 @@@ public class WebInterface 
        /** The logger. */
        private static final Logger logger = getLogger(WebInterface.class.getName());
  
+       /** The loaders for templates, pages, and classpath providers. */
+       private final Loaders loaders;
        /** The notification manager. */
        private final NotificationManager notificationManager = new NotificationManager();
  
  
        /** The parser filter. */
        private final ParserFilter parserFilter;
 +      private final RenderFilter renderFilter;
  
        /** The “new Sone” notification. */
        private final ListNotification<Sone> newSoneNotification;
         *            The Sone plugin
         */
        @Inject
-       public WebInterface(SonePlugin sonePlugin) {
+       public WebInterface(SonePlugin sonePlugin, Loaders loaders) {
                this.sonePlugin = sonePlugin;
+               this.loaders = loaders;
                formPassword = sonePlugin.pluginRespirator().getToadletContainer().getFormPassword();
 -              soneTextParser = new SoneTextParser(getCore(), getCore());
 +              soneTextParser = new SoneTextParser(getCore(), getCore(), getCore());
  
                templateContextFactory = new TemplateContextFactory();
                templateContextFactory.addAccessor(Object.class, new ReflectionAccessor());
                templateContextFactory.addFilter("match", new MatchFilter());
                templateContextFactory.addFilter("css", new CssClassNameFilter());
                templateContextFactory.addFilter("js", new JavascriptFilter());
 -              templateContextFactory.addFilter("parse", parserFilter = new ParserFilter(getCore(), templateContextFactory, soneTextParser));
 +              templateContextFactory.addFilter("parse", parserFilter = new ParserFilter(getCore(), soneTextParser));
                templateContextFactory.addFilter("reparse", new ReparseFilter());
 +              templateContextFactory.addFilter("render", renderFilter = new RenderFilter(getCore(), templateContextFactory));
                templateContextFactory.addFilter("unknown", new UnknownDateFilter(getL10n(), "View.Sone.Text.UnknownDate"));
                templateContextFactory.addFilter("format", new FormatFilter());
                templateContextFactory.addFilter("sort", new CollectionSortFilter());
                templateContextFactory.addFilter("unique", new UniqueElementFilter());
                templateContextFactory.addFilter("mod", new ModFilter());
                templateContextFactory.addFilter("paginate", new PaginationFilter());
 +              templateContextFactory.addFilter("build-id", new BuildIdFilter());
                templateContextFactory.addProvider(TemplateProvider.TEMPLATE_CONTEXT_PROVIDER);
-               templateContextFactory.addProvider(new ClassPathTemplateProvider(WebInterface.class, "/templates/"));
+               templateContextFactory.addProvider(loaders.getTemplateProvider());
                templateContextFactory.addTemplateObject("webInterface", this);
                templateContextFactory.addTemplateObject("formPassword", formPassword);
  
                /* create notifications. */
-               Template newSoneNotificationTemplate = parseTemplate("/templates/notify/newSoneNotification.html");
+               Template newSoneNotificationTemplate = loaders.loadTemplate("/templates/notify/newSoneNotification.html");
                newSoneNotification = new ListNotification<Sone>("new-sone-notification", "sones", newSoneNotificationTemplate, false);
  
-               Template newPostNotificationTemplate = parseTemplate("/templates/notify/newPostNotification.html");
+               Template newPostNotificationTemplate = loaders.loadTemplate("/templates/notify/newPostNotification.html");
                newPostNotification = new ListNotification<Post>("new-post-notification", "posts", newPostNotificationTemplate, false);
  
-               Template localPostNotificationTemplate = parseTemplate("/templates/notify/newPostNotification.html");
+               Template localPostNotificationTemplate = loaders.loadTemplate("/templates/notify/newPostNotification.html");
                localPostNotification = new ListNotification<Post>("local-post-notification", "posts", localPostNotificationTemplate, false);
  
-               Template newReplyNotificationTemplate = parseTemplate("/templates/notify/newReplyNotification.html");
+               Template newReplyNotificationTemplate = loaders.loadTemplate("/templates/notify/newReplyNotification.html");
                newReplyNotification = new ListNotification<PostReply>("new-reply-notification", "replies", newReplyNotificationTemplate, false);
  
-               Template localReplyNotificationTemplate = parseTemplate("/templates/notify/newReplyNotification.html");
+               Template localReplyNotificationTemplate = loaders.loadTemplate("/templates/notify/newReplyNotification.html");
                localReplyNotification = new ListNotification<PostReply>("local-reply-notification", "replies", localReplyNotificationTemplate, false);
  
-               Template mentionNotificationTemplate = parseTemplate("/templates/notify/mentionNotification.html");
+               Template mentionNotificationTemplate = loaders.loadTemplate("/templates/notify/mentionNotification.html");
                mentionNotification = new ListNotification<Post>("mention-notification", "posts", mentionNotificationTemplate, false);
  
-               Template lockedSonesTemplate = parseTemplate("/templates/notify/lockedSonesNotification.html");
+               Template lockedSonesTemplate = loaders.loadTemplate("/templates/notify/lockedSonesNotification.html");
                lockedSonesNotification = new ListNotification<Sone>("sones-locked-notification", "sones", lockedSonesTemplate);
  
-               Template newVersionTemplate = parseTemplate("/templates/notify/newVersionNotification.html");
+               Template newVersionTemplate = loaders.loadTemplate("/templates/notify/newVersionNotification.html");
                newVersionNotification = new TemplateNotification("new-version-notification", newVersionTemplate);
  
-               Template insertingImagesTemplate = parseTemplate("/templates/notify/inserting-images-notification.html");
+               Template insertingImagesTemplate = loaders.loadTemplate("/templates/notify/inserting-images-notification.html");
                insertingImagesNotification = new ListNotification<Image>("inserting-images-notification", "images", insertingImagesTemplate);
  
-               Template insertedImagesTemplate = parseTemplate("/templates/notify/inserted-images-notification.html");
+               Template insertedImagesTemplate = loaders.loadTemplate("/templates/notify/inserted-images-notification.html");
                insertedImagesNotification = new ListNotification<Image>("inserted-images-notification", "images", insertedImagesTemplate);
  
-               Template imageInsertFailedTemplate = parseTemplate("/templates/notify/image-insert-failed-notification.html");
+               Template imageInsertFailedTemplate = loaders.loadTemplate("/templates/notify/image-insert-failed-notification.html");
                imageInsertFailedNotification = new ListNotification<Image>("image-insert-failed-notification", "images", imageInsertFailedTemplate);
        }
  
-       private Template parseTemplate(String resourceName) {
-               InputStream templateInputStream = null;
-               Reader reader = null;
-               try {
-                       templateInputStream = getClass().getResourceAsStream(resourceName);
-                       reader = new InputStreamReader(templateInputStream, "UTF-8");
-                       return parse(reader);
-               } catch (UnsupportedEncodingException uee1) {
-                       throw new RuntimeException("UTF-8 not supported.");
-               } finally {
-                       Closer.close(reader);
-                       Closer.close(templateInputStream);
-               }
-       }
        //
        // ACCESSORS
        //
         */
        public void setFirstStart(boolean firstStart) {
                if (firstStart) {
-                       Template firstStartNotificationTemplate = parseTemplate("/templates/notify/firstStartNotification.html");
+                       Template firstStartNotificationTemplate = loaders.loadTemplate("/templates/notify/firstStartNotification.html");
                        Notification firstStartNotification = new TemplateNotification("first-start-notification", firstStartNotificationTemplate);
                        notificationManager.addNotification(firstStartNotification);
                }
         */
        public void setNewConfig(boolean newConfig) {
                if (newConfig && !hasFirstStartNotification()) {
-                       Template configNotReadNotificationTemplate = parseTemplate("/templates/notify/configNotReadNotification.html");
+                       Template configNotReadNotificationTemplate = loaders.loadTemplate("/templates/notify/configNotReadNotification.html");
                        Notification configNotReadNotification = new TemplateNotification("config-not-read-notification", configNotReadNotificationTemplate);
                        notificationManager.addNotification(configNotReadNotification);
                }
                registerToadlets();
  
                /* notification templates. */
-               Template startupNotificationTemplate = parseTemplate("/templates/notify/startupNotification.html");
+               Template startupNotificationTemplate = loaders.loadTemplate("/templates/notify/startupNotification.html");
  
                final TemplateNotification startupNotification = new TemplateNotification("startup-notification", startupNotificationTemplate);
                notificationManager.addNotification(startupNotification);
                        }
                }, 2, TimeUnit.MINUTES);
  
-               Template wotMissingNotificationTemplate = parseTemplate("/templates/notify/wotMissingNotification.html");
+               Template wotMissingNotificationTemplate = loaders.loadTemplate("/templates/notify/wotMissingNotification.html");
                final TemplateNotification wotMissingNotification = new TemplateNotification("wot-missing-notification", wotMissingNotificationTemplate);
                ticker.scheduleAtFixedRate(new Runnable() {
  
         */
        private void registerToadlets() {
                Template emptyTemplate = parse(new StringReader(""));
-               Template loginTemplate = parseTemplate("/templates/login.html");
-               Template indexTemplate = parseTemplate("/templates/index.html");
-               Template newTemplate = parseTemplate("/templates/new.html");
-               Template knownSonesTemplate = parseTemplate("/templates/knownSones.html");
-               Template createSoneTemplate = parseTemplate("/templates/createSone.html");
-               Template createPostTemplate = parseTemplate("/templates/createPost.html");
-               Template createReplyTemplate = parseTemplate("/templates/createReply.html");
-               Template bookmarksTemplate = parseTemplate("/templates/bookmarks.html");
-               Template searchTemplate = parseTemplate("/templates/search.html");
-               Template editProfileTemplate = parseTemplate("/templates/editProfile.html");
-               Template editProfileFieldTemplate = parseTemplate("/templates/editProfileField.html");
-               Template deleteProfileFieldTemplate = parseTemplate("/templates/deleteProfileField.html");
-               Template viewSoneTemplate = parseTemplate("/templates/viewSone.html");
-               Template viewPostTemplate = parseTemplate("/templates/viewPost.html");
-               Template deletePostTemplate = parseTemplate("/templates/deletePost.html");
-               Template deleteReplyTemplate = parseTemplate("/templates/deleteReply.html");
-               Template deleteSoneTemplate = parseTemplate("/templates/deleteSone.html");
-               Template imageBrowserTemplate = parseTemplate("/templates/imageBrowser.html");
-               Template createAlbumTemplate = parseTemplate("/templates/createAlbum.html");
-               Template deleteAlbumTemplate = parseTemplate("/templates/deleteAlbum.html");
-               Template deleteImageTemplate = parseTemplate("/templates/deleteImage.html");
-               Template noPermissionTemplate = parseTemplate("/templates/noPermission.html");
-               Template emptyImageTitleTemplate = parseTemplate("/templates/emptyImageTitle.html");
-               Template emptyAlbumTitleTemplate = parseTemplate("/templates/emptyAlbumTitle.html");
-               Template optionsTemplate = parseTemplate("/templates/options.html");
-               Template rescueTemplate = parseTemplate("/templates/rescue.html");
-               Template aboutTemplate = parseTemplate("/templates/about.html");
-               Template invalidTemplate = parseTemplate("/templates/invalid.html");
-               Template postTemplate = parseTemplate("/templates/include/viewPost.html");
-               Template replyTemplate = parseTemplate("/templates/include/viewReply.html");
-               Template openSearchTemplate = parseTemplate("/templates/xml/OpenSearch.xml");
+               Template loginTemplate = loaders.loadTemplate("/templates/login.html");
+               Template indexTemplate = loaders.loadTemplate("/templates/index.html");
+               Template newTemplate = loaders.loadTemplate("/templates/new.html");
+               Template knownSonesTemplate = loaders.loadTemplate("/templates/knownSones.html");
+               Template createSoneTemplate = loaders.loadTemplate("/templates/createSone.html");
+               Template createPostTemplate = loaders.loadTemplate("/templates/createPost.html");
+               Template createReplyTemplate = loaders.loadTemplate("/templates/createReply.html");
+               Template bookmarksTemplate = loaders.loadTemplate("/templates/bookmarks.html");
+               Template searchTemplate = loaders.loadTemplate("/templates/search.html");
+               Template editProfileTemplate = loaders.loadTemplate("/templates/editProfile.html");
+               Template editProfileFieldTemplate = loaders.loadTemplate("/templates/editProfileField.html");
+               Template deleteProfileFieldTemplate = loaders.loadTemplate("/templates/deleteProfileField.html");
+               Template viewSoneTemplate = loaders.loadTemplate("/templates/viewSone.html");
+               Template viewPostTemplate = loaders.loadTemplate("/templates/viewPost.html");
+               Template deletePostTemplate = loaders.loadTemplate("/templates/deletePost.html");
+               Template deleteReplyTemplate = loaders.loadTemplate("/templates/deleteReply.html");
+               Template deleteSoneTemplate = loaders.loadTemplate("/templates/deleteSone.html");
+               Template imageBrowserTemplate = loaders.loadTemplate("/templates/imageBrowser.html");
+               Template createAlbumTemplate = loaders.loadTemplate("/templates/createAlbum.html");
+               Template deleteAlbumTemplate = loaders.loadTemplate("/templates/deleteAlbum.html");
+               Template deleteImageTemplate = loaders.loadTemplate("/templates/deleteImage.html");
+               Template noPermissionTemplate = loaders.loadTemplate("/templates/noPermission.html");
+               Template emptyImageTitleTemplate = loaders.loadTemplate("/templates/emptyImageTitle.html");
+               Template emptyAlbumTitleTemplate = loaders.loadTemplate("/templates/emptyAlbumTitle.html");
+               Template optionsTemplate = loaders.loadTemplate("/templates/options.html");
+               Template rescueTemplate = loaders.loadTemplate("/templates/rescue.html");
+               Template aboutTemplate = loaders.loadTemplate("/templates/about.html");
+               Template invalidTemplate = loaders.loadTemplate("/templates/invalid.html");
+               Template postTemplate = loaders.loadTemplate("/templates/include/viewPost.html");
+               Template replyTemplate = loaders.loadTemplate("/templates/include/viewReply.html");
+               Template openSearchTemplate = loaders.loadTemplate("/templates/xml/OpenSearch.xml");
  
                PageToadletFactory pageToadletFactory = new PageToadletFactory(sonePlugin.pluginRespirator().getHLSimpleClient(), "/Sone/");
                pageToadlets.add(pageToadletFactory.createPageToadlet(new RedirectPage<FreenetRequest>("", "index.html")));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new SoneTemplatePage("emptyAlbumTitle.html", emptyAlbumTitleTemplate, "Page.EmptyAlbumTitle.Title", this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new DismissNotificationPage(emptyTemplate, this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new SoneTemplatePage("invalid.html", invalidTemplate, "Page.Invalid.Title", this)));
-               pageToadlets.add(pageToadletFactory.createPageToadlet(new StaticPage<FreenetRequest>("css/", "/static/css/", "text/css")));
-               pageToadlets.add(pageToadletFactory.createPageToadlet(new StaticPage<FreenetRequest>("javascript/", "/static/javascript/", "text/javascript")));
-               pageToadlets.add(pageToadletFactory.createPageToadlet(new StaticPage<FreenetRequest>("images/", "/static/images/", "image/png")));
+               pageToadlets.add(pageToadletFactory.createPageToadlet(loaders.<FreenetRequest>loadStaticPage("css/", "/static/css/", "text/css")));
+               pageToadlets.add(pageToadletFactory.createPageToadlet(loaders.<FreenetRequest>loadStaticPage("javascript/", "/static/javascript/", "text/javascript")));
+               pageToadlets.add(pageToadletFactory.createPageToadlet(loaders.<FreenetRequest>loadStaticPage("images/", "/static/images/", "image/png")));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new TemplatePage<FreenetRequest>("OpenSearch.xml", "application/opensearchdescription+xml", templateContextFactory, openSearchTemplate)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new GetImagePage(this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new GetTranslationPage(this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new UnlockSoneAjaxPage(this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new FollowSoneAjaxPage(this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new UnfollowSoneAjaxPage(this)));
 -              pageToadlets.add(pageToadletFactory.createPageToadlet(new EditAlbumAjaxPage(this)));
 -              pageToadlets.add(pageToadletFactory.createPageToadlet(new EditImageAjaxPage(this, parserFilter)));
 +              pageToadlets.add(pageToadletFactory.createPageToadlet(new EditAlbumAjaxPage(this, parserFilter, renderFilter)));
 +              pageToadlets.add(pageToadletFactory.createPageToadlet(new EditImageAjaxPage(this, parserFilter, renderFilter)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new TrustAjaxPage(this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new DistrustAjaxPage(this)));
                pageToadlets.add(pageToadletFactory.createPageToadlet(new UntrustAjaxPage(this)));
                synchronized (soneInsertNotifications) {
                        TemplateNotification templateNotification = soneInsertNotifications.get(sone);
                        if (templateNotification == null) {
-                               templateNotification = new TemplateNotification(parseTemplate("/templates/notify/soneInsertNotification.html"));
+                               templateNotification = new TemplateNotification(loaders.loadTemplate("/templates/notify/soneInsertNotification.html"));
                                templateNotification.set("insertSone", sone);
                                soneInsertNotifications.put(sone, templateNotification);
                        }