0
|
1 package nabble.model;
|
|
2
|
|
3 import fschmidt.db.DbDatabase;
|
|
4 import fschmidt.db.DbNull;
|
|
5 import fschmidt.db.DbObject;
|
|
6 import fschmidt.db.DbObjectFactory;
|
|
7 import fschmidt.db.DbRecord;
|
|
8 import fschmidt.db.DbTable;
|
|
9 import fschmidt.db.Listener;
|
|
10 import fschmidt.db.LongKey;
|
|
11 import fschmidt.util.java.DateUtils;
|
|
12 import fschmidt.util.java.ObjectUtils;
|
|
13 import nabble.view.lib.Jtp;
|
|
14 import nabble.view.lib.SiteDeleteMail;
|
|
15 import org.slf4j.Logger;
|
|
16 import org.slf4j.LoggerFactory;
|
|
17
|
|
18 import java.sql.Connection;
|
|
19 import java.sql.PreparedStatement;
|
|
20 import java.sql.ResultSet;
|
|
21 import java.sql.SQLException;
|
|
22 import java.sql.Statement;
|
|
23 import java.util.ArrayList;
|
|
24 import java.util.Date;
|
|
25 import java.util.List;
|
|
26 import java.util.Map;
|
|
27 import java.util.WeakHashMap;
|
|
28
|
|
29
|
|
30 final class SiteGlobal implements DbObject<LongKey,SiteGlobal> {
|
|
31 private static final Logger logger = LoggerFactory.getLogger(SiteGlobal.class);
|
|
32
|
|
33 final SiteKey siteKey;
|
|
34 private final DbRecord<LongKey,SiteGlobal> record;
|
|
35 private String customDomain;
|
|
36 private Date deleteDate;
|
|
37 private int activity;
|
|
38 private boolean isEmbarrassing = false;
|
|
39 private String remoteAddr = null; // IP of the user who created the site
|
|
40 private String baseUrl;
|
|
41
|
|
42 SiteGlobal() {
|
|
43 record = table.newRecord(this);
|
|
44 record.insert();
|
|
45 this.siteKey = SiteKey.getInstance(getId());
|
|
46 }
|
|
47
|
|
48 SiteGlobal(long siteId) {
|
|
49 record = table.newRecord(this);
|
|
50 record.fields().put("site_id", siteId );
|
|
51 record.insert();
|
|
52 this.siteKey = SiteKey.getInstance(getId());
|
|
53 }
|
|
54
|
|
55 private SiteGlobal(LongKey key,ResultSet rs)
|
|
56 throws SQLException
|
|
57 {
|
|
58 record = table.newRecord(this,key);
|
|
59 this.siteKey = SiteKey.getInstance(getId());
|
|
60 customDomain = rs.getString("custom_domain");
|
|
61 if( customDomain != null )
|
|
62 customDomain = customDomain.intern();
|
|
63 deleteDate = rs.getDate("delete_date");
|
|
64 activity = rs.getInt("activity");
|
|
65 isEmbarrassing = rs.getBoolean("is_embarrassing");
|
|
66 remoteAddr = rs.getString("remote_addr");
|
|
67 }
|
|
68
|
|
69 public DbRecord<LongKey,SiteGlobal> getDbRecord() {
|
|
70 return record;
|
|
71 }
|
|
72
|
|
73 public long getId() {
|
|
74 return record.getPrimaryKey().value();
|
|
75 }
|
|
76
|
|
77 private DbTable<LongKey,SiteGlobal> table() {
|
|
78 return record.getDbTable();
|
|
79 }
|
|
80
|
|
81 private DbDatabase db() {
|
|
82 return table().getDbDatabase();
|
|
83 }
|
|
84
|
|
85 SiteImpl site() {
|
|
86 return siteKey.site();
|
|
87 }
|
|
88
|
|
89 static DbTable<LongKey,SiteGlobal> table = Db.dbGlobal().newTable(
|
|
90 "site_global",
|
|
91 Db.dbGlobal().newIdentityLongKeySetter("site_id"),
|
|
92 new DbObjectFactory<LongKey, SiteGlobal>() {
|
|
93 public SiteGlobal makeDbObject(LongKey key,ResultSet rs,String tableName)
|
|
94 throws SQLException
|
|
95 {
|
|
96 return new SiteGlobal(key,rs);
|
|
97 }
|
|
98 }
|
|
99 );
|
|
100 static {
|
|
101 table.getPostUpdateListeners().add(new Listener<SiteGlobal>() {
|
|
102 public void event(SiteGlobal siteGlobal) {
|
|
103 SiteImpl.postUpdateListeners.event(siteGlobal.site());
|
|
104 }
|
|
105 } );
|
|
106 /*
|
|
107 // for debugging
|
|
108 table.getPreDeleteListeners().add(new Listener<SiteGlobal>() {
|
|
109 public void event(SiteGlobal siteGlobal) {
|
|
110 logger.error("deleting "+siteGlobal,new Exception());
|
|
111 }
|
|
112 } );
|
|
113 */
|
|
114 }
|
|
115
|
|
116 static SiteGlobal getSiteGlobal(long siteId) {
|
|
117 return table.findByPrimaryKey(new LongKey(siteId));
|
|
118 }
|
|
119
|
|
120 static SiteGlobal getSiteGlobal(ResultSet rs)
|
|
121 throws SQLException
|
|
122 {
|
|
123 return table.getDbObject(rs);
|
|
124 }
|
|
125
|
|
126 public void setCustomDomain(String customDomain) {
|
|
127 if( customDomain != null )
|
|
128 customDomain = customDomain.toLowerCase();
|
|
129 this.customDomain = customDomain;
|
|
130 record.fields().put("custom_domain", DbNull.fix(customDomain) );
|
|
131 if( !db().isInTransaction() )
|
|
132 record.update();
|
|
133 // calcBaseUrl();
|
|
134 }
|
|
135
|
|
136 public String getCustomDomain() {
|
|
137 return customDomain;
|
|
138 }
|
|
139
|
|
140 public String getBaseUrl() {
|
|
141 if( baseUrl == null ) {
|
|
142 baseUrl = "http://" +
|
|
143 (customDomain != null ? customDomain : Jtp.getDefaultBaseUrl(siteKey.site()));
|
|
144 }
|
|
145 return baseUrl;
|
|
146 }
|
|
147 /*
|
|
148 void calcBaseUrl() {
|
|
149 baseUrl = "http://" +
|
|
150 (customDomain != null ? customDomain : Jtp.getDefaultBaseUrl(siteKey.site()));
|
|
151 }
|
|
152 */
|
|
153
|
|
154
|
|
155 private static final Map<String,Long> domainMap = new WeakHashMap<String,Long>();
|
|
156
|
|
157 static Long getSiteIdFromDomain(String customDomain) {
|
|
158 Long siteId;
|
|
159 synchronized(domainMap) {
|
|
160 siteId = domainMap.get(customDomain);
|
|
161 if( siteId == null ) {
|
|
162 try {
|
|
163 Connection con = Db.dbGlobal().getConnection();
|
|
164 try {
|
|
165 PreparedStatement stmt = con.prepareStatement(
|
|
166 "select site_id from site_global where custom_domain = ?"
|
|
167 );
|
|
168 stmt.setString(1,customDomain);
|
|
169 ResultSet rs = stmt.executeQuery();
|
|
170 try {
|
|
171 if( !rs.next() )
|
|
172 return null;
|
|
173 siteId = rs.getLong("site_id");
|
|
174 } finally {
|
|
175 rs.close();
|
|
176 stmt.close();
|
|
177 }
|
|
178 } finally {
|
|
179 con.close();
|
|
180 }
|
|
181 } catch(SQLException e) {
|
|
182 throw new RuntimeException(e);
|
|
183 }
|
|
184 domainMap.put( customDomain.intern(), siteId );
|
|
185 }
|
|
186 }
|
|
187 return siteId;
|
|
188 }
|
|
189
|
|
190
|
|
191
|
|
192
|
|
193 public int getActivity() {
|
|
194 return activity;
|
|
195 }
|
|
196
|
|
197 void setActivity(int activity) {
|
|
198 this.activity = activity;
|
|
199 record.fields().put( "activity", activity );
|
|
200 if( !db().isInTransaction() )
|
|
201 record.update();
|
|
202 }
|
|
203
|
|
204
|
|
205 public Date getDeleteDate() {
|
|
206 return deleteDate;
|
|
207 }
|
|
208
|
|
209 private void setDeleteDate(Date deleteDate) {
|
|
210 if( deleteDate==null )
|
|
211 throw new NullPointerException();
|
|
212 this.deleteDate = deleteDate;
|
|
213 record.fields().put("delete_date",deleteDate);
|
|
214 record.update();
|
|
215 }
|
|
216
|
|
217 public void clearDeleteDate() {
|
|
218 record.fields().put("delete_date",DbNull.TIMESTAMP);
|
|
219 record.fields().put("activity",ViewCount.initialActivity);
|
|
220 record.update();
|
|
221 }
|
|
222
|
|
223 private static final boolean deleteInactiveSites = Init.hasDaemons && Init.get("deleteInactiveSites",false);
|
|
224 private static final int daysToDeletion = Init.get("daysToDeletion",30);
|
|
225
|
|
226 private static void deleteInactiveSites() {
|
|
227 logger.error("Starting deleteInactiveSites");
|
|
228 List<SiteGlobal> sitesToDelete = new ArrayList<SiteGlobal>();
|
|
229 try {
|
|
230 Date deletionDate = DateUtils.addDays(new Date(),daysToDeletion);
|
|
231 Connection con = Db.dbGlobal().getConnection();
|
|
232 try {
|
|
233 {
|
|
234 Statement stmt = con.createStatement();
|
|
235 ResultSet rs = stmt.executeQuery(
|
|
236 "select * from site_global"
|
|
237 +" where delete_date is null and activity=0"
|
|
238 );
|
|
239 int count = 0;
|
|
240 while( rs.next() ) {
|
|
241 SiteGlobal siteGlobal = SiteGlobal.getSiteGlobal(rs);
|
|
242 try {
|
|
243 SiteImpl site = siteGlobal.site();
|
|
244 siteGlobal.setDeleteDate(deletionDate);
|
|
245 count++;
|
|
246 for( UserImpl user : site.getPosters() ) {
|
|
247 if( !user.isRegistered() )
|
|
248 continue;
|
|
249 // Send an email if site has more than one node
|
|
250 if (site.getRootNode().getDescendantCount() > 1) {
|
|
251 SiteDeleteMail.send(user,site,daysToDeletion);
|
|
252 logger.info("Site deletion email sent to " + user.getEmail() + " for " + site);
|
|
253 } else
|
|
254 logger.info("Site scheduled for deletion: " + site);
|
|
255 }
|
|
256 } catch(UpdatingException e) {
|
|
257 logger.error("Couldn't schedule for deletion: " + e);
|
|
258 }
|
|
259 if( Executors.isShuttingDown() )
|
|
260 return;
|
|
261 }
|
|
262 rs.close();
|
|
263 stmt.close();
|
|
264 logger.error("Sites scheduled for deletion = " + count);
|
|
265 }
|
|
266 {
|
|
267 Statement stmt = con.createStatement();
|
|
268 ResultSet rs = stmt.executeQuery(
|
|
269 "select * from site_global"
|
|
270 +" where delete_date < now()"
|
|
271 );
|
|
272 while( rs.next() ) {
|
|
273 SiteGlobal siteGlobal = SiteGlobal.getSiteGlobal(rs);
|
|
274 sitesToDelete.add(siteGlobal);
|
|
275 }
|
|
276 rs.close();
|
|
277 stmt.close();
|
|
278 }
|
|
279 } finally {
|
|
280 con.close();
|
|
281 }
|
|
282 } catch(SQLException e) {
|
|
283 throw new RuntimeException(e);
|
|
284 }
|
|
285 for( SiteGlobal siteGlobal : sitesToDelete ) {
|
|
286 try {
|
|
287 Site site = siteGlobal.site();
|
|
288 logger.error("Deleting inactive site ID=" + site.getId() + " (" + site.getRootNode().getSubject() + " / " + site.getRootNode().getDescendantCount() + " nodes)");
|
|
289 site.delete();
|
|
290 } catch(UpdatingException e) {
|
|
291 logger.error("Couldn't delete inactive site: " + e);
|
|
292 } catch(RuntimeException e) {
|
|
293 logger.error("couldn't delete inactive site "+siteGlobal,e);
|
|
294 }
|
|
295 }
|
|
296 logger.error("Finished deleteInactiveSites");
|
|
297 }
|
|
298
|
|
299 static {
|
|
300 if( deleteInactiveSites ) {
|
|
301 Executors.runDaily(new Runnable(){public void run(){
|
|
302 deleteInactiveSites();
|
|
303 }});
|
|
304 }
|
|
305 }
|
|
306
|
|
307
|
|
308 public boolean isEmbarrassing() {
|
|
309 return isEmbarrassing;
|
|
310 }
|
|
311
|
|
312 public void setEmbarrassing(boolean isEmbarrassing) {
|
|
313 this.isEmbarrassing = isEmbarrassing;
|
|
314 record.fields().put( "is_embarrassing", DbNull.fix(isEmbarrassing) );
|
|
315 if( !db().isInTransaction() )
|
|
316 record.update();
|
|
317 }
|
|
318
|
|
319 public String toString() {
|
|
320 return "siteGlobal-"+getId();
|
|
321 }
|
|
322
|
|
323 @Override public boolean equals(Object obj) {
|
|
324 return this==obj || obj instanceof SiteGlobal && record.isInDb() && ((SiteGlobal)obj).getId()==getId();
|
|
325 }
|
|
326
|
|
327 @Override public int hashCode() {
|
|
328 return (int)getId();
|
|
329 }
|
|
330
|
|
331
|
|
332 boolean setRemoteAddr(String remoteAddr) {
|
|
333 this.remoteAddr = remoteAddr;
|
|
334 record.fields().put( "remote_addr", DbNull.fix(remoteAddr) );
|
|
335 record.update();
|
|
336 return true;
|
|
337 }
|
|
338
|
|
339 }
|