Mercurial Hosting > nabble
comparison src/nabble/model/NodeImpl.java @ 47:72765b66e2c3
remove mailing list code
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Fri, 18 Jun 2021 17:44:24 -0600 |
parents | 7ecd1a4ef557 |
children |
comparison
equal
deleted
inserted
replaced
46:7ac7f55e16cf | 47:72765b66e2c3 |
---|---|
47 import java.util.WeakHashMap; | 47 import java.util.WeakHashMap; |
48 import java.util.concurrent.CopyOnWriteArrayList; | 48 import java.util.concurrent.CopyOnWriteArrayList; |
49 import java.util.concurrent.TimeUnit; | 49 import java.util.concurrent.TimeUnit; |
50 | 50 |
51 | 51 |
52 final class NodeImpl implements Node, Node.MailFromList { | 52 final class NodeImpl implements Node { |
53 private static final Logger logger = LoggerFactory.getLogger(NodeImpl.class); | 53 private static final Logger logger = LoggerFactory.getLogger(NodeImpl.class); |
54 | 54 |
55 private static final Message DELETED_MESSAGE = new Message("- deleted -", Message.Format.TEXT) { | 55 private static final Message DELETED_MESSAGE = new Message("- deleted -", Message.Format.TEXT) { |
56 public boolean isDeleted() { return true; } | 56 public boolean isDeleted() { return true; } |
57 public boolean isDeactivated() { return true; } | 57 public boolean isDeactivated() { return true; } |
64 private Date whenCreated; | 64 private Date whenCreated; |
65 private long ownerId; | 65 private long ownerId; |
66 private UserImpl owner; | 66 private UserImpl owner; |
67 private long parentId = 0L; | 67 private long parentId = 0L; |
68 private NodeImpl parent; | 68 private NodeImpl parent; |
69 private String messageID; | |
70 private Date whenUpdated; | 69 private Date whenUpdated; |
71 private Boolean isGuessedParent = false; | |
72 private Date whenSent; | |
73 private long lastNodeId; | 70 private long lastNodeId; |
74 private Date lastNodeDate; | 71 private Date lastNodeDate; |
75 private int nodeCount; | 72 private int nodeCount; |
76 private Kind kind; | 73 private Kind kind; |
77 private String type; | 74 private String type; |
93 Message.Format msgFmt = Message.Format.getMessageFormat( rs.getString("msg_fmt").charAt(0) ); | 90 Message.Format msgFmt = Message.Format.getMessageFormat( rs.getString("msg_fmt").charAt(0) ); |
94 message = new MyMessage(msgFmt); | 91 message = new MyMessage(msgFmt); |
95 whenCreated = rs.getTimestamp("when_created"); | 92 whenCreated = rs.getTimestamp("when_created"); |
96 ownerId = rs.getLong("owner_id"); | 93 ownerId = rs.getLong("owner_id"); |
97 parentId = rs.getLong("parent_id"); | 94 parentId = rs.getLong("parent_id"); |
98 messageID = rs.getString("message_id"); | |
99 whenUpdated = rs.getTimestamp("when_updated"); | 95 whenUpdated = rs.getTimestamp("when_updated"); |
100 isGuessedParent = rs.getBoolean("guessed_parent"); | |
101 if (rs.wasNull()) isGuessedParent = null; | |
102 whenSent = rs.getTimestamp("when_sent"); | |
103 lastNodeId = rs.getLong("last_node_id"); | 96 lastNodeId = rs.getLong("last_node_id"); |
104 lastNodeDate = rs.getTimestamp("last_node_date"); | 97 lastNodeDate = rs.getTimestamp("last_node_date"); |
105 nodeCount = rs.getInt("node_count"); | 98 nodeCount = rs.getInt("node_count"); |
106 kind = rs.getBoolean("is_app") ? Kind.APP : Kind.POST; | 99 kind = rs.getBoolean("is_app") ? Kind.APP : Kind.POST; |
107 type = rs.getString("type"); | 100 type = rs.getString("type"); |
270 | 263 |
271 private static final long TEN_MINUTES = 10 * 60 * 1000; | 264 private static final long TEN_MINUTES = 10 * 60 * 1000; |
272 | 265 |
273 private void setWhenUpdated() { | 266 private void setWhenUpdated() { |
274 long timeDiff = new Date().getTime() - getWhenCreated().getTime(); | 267 long timeDiff = new Date().getTime() - getWhenCreated().getTime(); |
275 boolean acceptChanges = timeDiff > TEN_MINUTES || !getChildren().isEmpty() || isMailToList(); | 268 boolean acceptChanges = timeDiff > TEN_MINUTES || !getChildren().isEmpty(); |
276 if (acceptChanges) { | 269 if (acceptChanges) { |
277 setWhenUpdated( new Date() ); | 270 setWhenUpdated( new Date() ); |
278 } | 271 } |
279 } | 272 } |
280 | 273 |
368 } finally { | 361 } finally { |
369 db().endTransaction(); | 362 db().endTransaction(); |
370 } | 363 } |
371 return; | 364 return; |
372 } | 365 } |
373 MailingListImpl mailingList = getMailingListImpl(); | |
374 if (mailingList != null) { | |
375 mailingList.unsubscribe(); | |
376 } | |
377 if( getChildCount() == 0 ) { | 366 if( getChildCount() == 0 ) { |
378 deleteRecursively(); | 367 deleteRecursively(); |
379 } else { | 368 } else { |
380 setMessage(DELETED_MESSAGE.getRaw(),DELETED_MESSAGE.getFormat()); | 369 setMessage(DELETED_MESSAGE.getRaw(),DELETED_MESSAGE.getFormat()); |
381 clearPending(); | |
382 update(); | 370 update(); |
383 } | 371 } |
384 } | 372 } |
385 | 373 |
386 private boolean isDeletedMessage() { | 374 private boolean isDeletedMessage() { |
470 if( isDoneByPoster ) { | 458 if( isDoneByPoster ) { |
471 UserImpl owner = getOwnerImpl(); | 459 UserImpl owner = getOwnerImpl(); |
472 if (owner != null) | 460 if (owner != null) |
473 owner.updateNewPostLimit(); | 461 owner.updateNewPostLimit(); |
474 } | 462 } |
475 if( isMailToList() && isDoneByPoster ) | |
476 throw new RuntimeException("no more pending"); | |
477 String message = (String)record.fields().remove("message"); | 463 String message = (String)record.fields().remove("message"); |
478 record.insert(); | 464 record.insert(); |
479 insertMessage(message); | 465 insertMessage(message); |
480 setLastNodeId( getId() ); | 466 setLastNodeId( getId() ); |
481 setLastNodeDate( whenCreated ); | 467 setLastNodeDate( whenCreated ); |
1161 postInsertListeners.add(listener); | 1147 postInsertListeners.add(listener); |
1162 } | 1148 } |
1163 | 1149 |
1164 static void addPostUpdateListener(final Listener<? super NodeImpl> listener) { | 1150 static void addPostUpdateListener(final Listener<? super NodeImpl> listener) { |
1165 postUpdateListeners.add(listener); | 1151 postUpdateListeners.add(listener); |
1166 Listener<MailingListImpl> mlListener = new Listener<MailingListImpl>() { | |
1167 public void event(MailingListImpl ml) { | |
1168 listener.event(ml.getForumImpl()); | |
1169 } | |
1170 }; | |
1171 MailingListImpl.postInsertListeners.add(mlListener); | |
1172 MailingListImpl.postUpdateListeners.add(mlListener); | |
1173 MailingListImpl.postDeleteListeners.add(mlListener); | |
1174 } | 1152 } |
1175 | 1153 |
1176 static void addPostDeleteListener(final Listener<? super NodeImpl> listener) { | 1154 static void addPostDeleteListener(final Listener<? super NodeImpl> listener) { |
1177 postDeleteListeners.add(listener); | 1155 postDeleteListeners.add(listener); |
1178 } | 1156 } |
1773 if( !record.fields().isEmpty() ) | 1751 if( !record.fields().isEmpty() ) |
1774 record.update(); | 1752 record.update(); |
1775 } | 1753 } |
1776 | 1754 |
1777 | 1755 |
1778 | |
1779 // mailing list related | |
1780 | |
1781 static final String messageIDEnding; | |
1782 static { | |
1783 try { | |
1784 messageIDEnding = ".post@" + Init.get("mailDomain",InetAddress.getLocalHost().getHostName()); | |
1785 } catch(UnknownHostException e) { | |
1786 logger.error("",e); | |
1787 System.exit(-1); | |
1788 throw new RuntimeException(); // for compiler | |
1789 } | |
1790 } | |
1791 | |
1792 public String getMessageID() { | |
1793 return messageID; | |
1794 } | |
1795 | |
1796 public MailFromList getParentMailFromList() { | |
1797 Node node = getParent(); | |
1798 return (node == null) ? null : node.getMailFromList(); | |
1799 } | |
1800 | |
1801 public String getOrGenerateMessageID() { | |
1802 if (messageID == null) { | |
1803 String id = "" + System.currentTimeMillis() + "-" + getId() + messageIDEnding; | |
1804 setMessageID(id); | |
1805 if( isInDb() ) | |
1806 this.record.update(); | |
1807 } | |
1808 return messageID; | |
1809 } | |
1810 | |
1811 void setMessageID(String messageID) { | |
1812 this.messageID = messageID; | |
1813 record.fields().put("message_id",messageID); | |
1814 } | |
1815 | |
1816 void setGuessedParent(NodeImpl newParent) | |
1817 throws ModelException | |
1818 { | |
1819 setGuessedParent(true); | |
1820 changeParentImpl(newParent); | |
1821 } | |
1822 | |
1823 boolean isGuessedParent() { | |
1824 return (isGuessedParent != null) && isGuessedParent; | |
1825 } | |
1826 | |
1827 boolean isNotGuessedParent() { | |
1828 return (isGuessedParent != null) && !isGuessedParent; | |
1829 } | |
1830 | |
1831 public boolean hasGuessedParent() { | |
1832 return isGuessedParent(); | |
1833 } | |
1834 | |
1835 Boolean rawGuessedParent() { | |
1836 return isGuessedParent; | |
1837 } | |
1838 | |
1839 /** | |
1840 * Set 'guessed_parent' flag of the post. | |
1841 * | |
1842 * @param guessed flag value | |
1843 */ | |
1844 void setGuessedParent(Boolean guessed) { | |
1845 this.isGuessedParent = guessed; | |
1846 record.fields().put("guessed_parent", DbNull.fix(this.isGuessedParent) ); | |
1847 } | |
1848 | |
1849 void setGuessedParent(String parentID) { | |
1850 setGuessedParent(Boolean.TRUE); | |
1851 setRawParentMessageId(parentID); | |
1852 } | |
1853 | |
1854 // only returns MailingList if not isUIHidden | |
1855 public MailingList getAssociatedMailingList() { | |
1856 return getAssociatedMailingListImpl(); | |
1857 } | |
1858 | |
1859 MailingListImpl getAssociatedMailingListImpl() { | |
1860 for( NodeImpl node=this; node!=null; node=node.getParentImpl() ) { | |
1861 if( node.getKind()==Kind.APP ) { | |
1862 MailingListImpl ml = node.getMailingListImpl(); | |
1863 if( ml != null ) | |
1864 return ml; | |
1865 } | |
1866 } | |
1867 return null; | |
1868 } | |
1869 | |
1870 boolean isFromMailingList() { | |
1871 return message.getFormat() == Message.Format.MAILING_LIST; | |
1872 } | |
1873 | |
1874 void clearPending() { | |
1875 whenSent = null; | |
1876 record.fields().put("when_sent", DbNull.TIMESTAMP); | |
1877 if( !db().isInTransaction() ) { | |
1878 record.update(); | |
1879 DbUtils.uncache(getOwnerImpl()); | |
1880 } | |
1881 } | |
1882 | |
1883 private boolean isMailToList() { | |
1884 return getKind() == Kind.POST && getAssociatedMailingListImpl() != null && !isFromMailingList(); | |
1885 } | |
1886 | |
1887 public MailToList getMailToList() { | |
1888 if( !isMailToList() ) | |
1889 return null; | |
1890 return new MailToList() { | |
1891 | |
1892 public Node getNode() { | |
1893 return NodeImpl.this; | |
1894 } | |
1895 | |
1896 public boolean isPending() { | |
1897 return whenSent != null; | |
1898 } | |
1899 | |
1900 public void clearPending() { | |
1901 NodeImpl.this.clearPending(); | |
1902 } | |
1903 | |
1904 public Date getWhenSent() { | |
1905 return whenSent; | |
1906 } | |
1907 | |
1908 public String getOrGenerateMessageID() { | |
1909 return NodeImpl.this.getOrGenerateMessageID(); | |
1910 } | |
1911 | |
1912 }; | |
1913 } | |
1914 | |
1915 | |
1916 public MailFromList getMailFromList() { | |
1917 // MailFromList is used to work with all messages from mailing lists, both local and external | |
1918 return (getKind() == Kind.POST && getAssociatedMailingListImpl() != null) ? this : null; | |
1919 } | |
1920 | |
1921 public MailingList newMailingList(ListServer listServer,String listAddress,String url) throws ModelException { | |
1922 if( getKind() != Kind.APP ) | |
1923 throw new UnsupportedOperationException(); | |
1924 if( !ModelHome.insideImportProcedure.get() ) | |
1925 DailyNumber.forumsStarted.dec(); | |
1926 setMailingList(new MailingListImpl(this, listServer, listAddress, url)); | |
1927 DbUtils.uncache(this); | |
1928 return mailingList; | |
1929 } | |
1930 | |
1931 private void setRawParentMessageId(String parentMessageId) { | |
1932 record.fields().put("parent_message_id", DbNull.fix(parentMessageId)); | |
1933 } | |
1934 | |
1935 static NodeImpl[] getFromParentID(String parentID, MailingListImpl mailingList) { | |
1936 try { | |
1937 SiteKey siteKey = mailingList.siteKey; | |
1938 Connection con = siteKey.getDb().getConnection(); | |
1939 PreparedStatement stmt = con.prepareStatement( | |
1940 "select *" | |
1941 +" from node" | |
1942 +" where lower(parent_message_id)=?" | |
1943 ); | |
1944 stmt.setString(1,parentID.toLowerCase()); | |
1945 ResultSet rs = stmt.executeQuery(); | |
1946 try { | |
1947 List<NodeImpl> list = new ArrayList<NodeImpl>(); | |
1948 while( rs.next() ) { | |
1949 NodeImpl post = getNode(siteKey,rs); | |
1950 if (mailingList.equals(post.getAssociatedMailingListImpl())) | |
1951 list.add( post ); | |
1952 } | |
1953 return list.toArray(new NodeImpl[0]); | |
1954 } finally { | |
1955 rs.close(); | |
1956 stmt.close(); | |
1957 con.close(); | |
1958 } | |
1959 } catch(SQLException e) { | |
1960 throw new RuntimeException(e); | |
1961 } | |
1962 } | |
1963 | |
1964 NodeImpl getNodeImplFromMessageID(String messageID) { | |
1965 if( messageID == null ) | |
1966 return null; | |
1967 try { | |
1968 Connection con = db().getConnection(); | |
1969 PreparedStatement stmt = con.prepareStatement( | |
1970 "select * from node" | |
1971 +" where lower(message_id)=? and message_id is not null" | |
1972 ); | |
1973 stmt.setString(1,messageID.toLowerCase()); | |
1974 ResultSet rs = stmt.executeQuery(); | |
1975 try { | |
1976 while (rs.next()) { | |
1977 NodeImpl post = getNode(rs); | |
1978 if( post.getAncestors().contains(this) ) | |
1979 return post; | |
1980 } | |
1981 return null; | |
1982 } finally { | |
1983 rs.close(); | |
1984 stmt.close(); | |
1985 con.close(); | |
1986 } | |
1987 } catch(SQLException e) { | |
1988 throw new RuntimeException(e); | |
1989 } | |
1990 } | |
1991 | |
1992 | |
1993 | |
1994 | |
1995 | |
1996 private MailingListImpl mailingList; | |
1997 private boolean mailingListSet = false; | |
1998 | |
1999 private void setMailingList(MailingListImpl mailingList) { | |
2000 this.mailingList = mailingList; | |
2001 mailingListSet = true; | |
2002 } | |
2003 | |
2004 MailingListImpl getMailingListImpl() { | |
2005 if( getKind() != Kind.APP ) | |
2006 return null; | |
2007 if (!mailingListSet || (mailingList != null && DbUtils.isStale(mailingList))) { | |
2008 setMailingList(MailingListImpl.getMailingListForForum(this)); | |
2009 } | |
2010 return mailingList; | |
2011 } | |
2012 | |
2013 public MailingList getMailingList() { | |
2014 return getMailingListImpl(); | |
2015 } | |
2016 | |
2017 public void deleteMailingList() { | |
2018 MailingList mailingList = getMailingList(); | |
2019 if (mailingList != null) { | |
2020 mailingList.delete(); | |
2021 this.mailingList = null; | |
2022 this.mailingListSet = false; | |
2023 DbUtils.uncache(this); | |
2024 } | |
2025 } | |
2026 | |
2027 | |
2028 | |
2029 | |
2030 // export/import | 1756 // export/import |
2031 | 1757 |
2032 NodeImpl(SiteImpl site,NodeData data) | 1758 NodeImpl(SiteImpl site,NodeData data) |
2033 throws ModelException | 1759 throws ModelException |
2034 { | 1760 { |
2049 if( data.whenUpdated != null ) | 1775 if( data.whenUpdated != null ) |
2050 setWhenUpdated( data.whenUpdated ); | 1776 setWhenUpdated( data.whenUpdated ); |
2051 setType( data.type ); | 1777 setType( data.type ); |
2052 if( data.pin != null ) | 1778 if( data.pin != null ) |
2053 record.fields().put( "pin", data.pin ); | 1779 record.fields().put( "pin", data.pin ); |
2054 if( data.messageID != null ) | |
2055 setMessageID( data.messageID ); | |
2056 setGuessedParent( data.isGuessedParent ); | |
2057 insert(false); | 1780 insert(false); |
2058 | |
2059 if( data.mlAddress != null ) { | |
2060 ListServer listServer = ListServer.getServer( data.mlServer ); | |
2061 MailingList mailingList = newMailingList( listServer, data.mlAddress, data.mlUrl ); | |
2062 mailingList.setPlainTextOnly( data.mlPlainTextOnly ); | |
2063 mailingList.setIgnoreNoArchive( data.mlIgnoreNoArchive ); | |
2064 mailingList.setListName( data.mlListName ); | |
2065 mailingList.update(); | |
2066 update(); | |
2067 } | |
2068 | 1781 |
2069 for( URL url : data.fileUrls ) { | 1782 for( URL url : data.fileUrls ) { |
2070 try { | 1783 try { |
2071 FileUpload.uploadFile( new FileUpload.UrlFileItem(url), this ); | 1784 FileUpload.uploadFile( new FileUpload.UrlFileItem(url), this ); |
2072 } catch(ModelException e) {} | 1785 } catch(ModelException e) {} |
2102 data.message = getMessage().getRaw(); | 1815 data.message = getMessage().getRaw(); |
2103 data.msgFmt = getMessage().getFormat().getCode(); | 1816 data.msgFmt = getMessage().getFormat().getCode(); |
2104 data.whenCreated = whenCreated; | 1817 data.whenCreated = whenCreated; |
2105 data.whenUpdated = whenUpdated; | 1818 data.whenUpdated = whenUpdated; |
2106 data.type = type; | 1819 data.type = type; |
2107 data.messageID = messageID; | |
2108 data.isGuessedParent = isGuessedParent; | |
2109 | |
2110 MailingListImpl mailingList = getMailingListImpl(); | |
2111 if( mailingList != null ) { | |
2112 data.mlAddress = mailingList.getListAddress(); | |
2113 data.mlUrl = mailingList.getUrl(); | |
2114 if( data.mlUrl==null ) | |
2115 data.mlUrl = "http://localhost"; | |
2116 data.mlPlainTextOnly = mailingList.plainTextOnly(); | |
2117 data.mlIgnoreNoArchive = mailingList.ignoreNoArchive(); | |
2118 data.mlServer = mailingList.getListServer().getType(); | |
2119 data.mlListName = mailingList.getListName(); | |
2120 } | |
2121 | 1820 |
2122 List<URL> urls = new ArrayList<URL>(); | 1821 List<URL> urls = new ArrayList<URL>(); |
2123 Message.Format fmt = message.getFormat(); | 1822 Message.Format fmt = message.getFormat(); |
2124 if( !(fmt instanceof MailMessageFormat) ) { | 1823 if( !(fmt instanceof MailMessageFormat) ) { |
2125 Html list = message.parse(); | 1824 Html list = message.parse(); |