001: /**
002: * Copyright (C) 2003 Manfred Andres
003: *
004: * This program is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU General Public License
006: * as published by the Free Software Foundation; either version 2
007: * of the License, or (at your option) any later version.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
012: * GNU General Public License for more details.
013: *
014: * You should have received a copy of the GNU General Public License
015: * along with this program; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
017: */package freecs.layout;
018:
019: import freecs.Server;
020: import freecs.util.FileMonitor;
021: import freecs.interfaces.IReloadable;
022:
023: import java.io.*;
024: import java.util.*;
025:
026: public class TemplateSet implements IReloadable {
027: private Hashtable tpl;
028: private Properties props;
029: public String name;
030: private int hashCode = Integer.MIN_VALUE;
031: private boolean isValide;
032:
033: private File msgSet;
034: private long lastModified;
035: private boolean msgSetPresent = false;
036: private TemplateManager tm;
037:
038: public TemplateSet(File dir, TemplateManager tm) throws IOException {
039: this .tm = tm;
040: this .isValide = false;
041: this .name = dir.getName();
042: this .tpl = createTemplates(dir);
043: if (!msgSetPresent) {
044: if (name.equals("default")) {
045: Server
046: .log(
047: this ,
048: "Default-templateset doesn't have a message.set-file",
049: Server.MSG_ERROR, Server.LVL_HALT);
050: } else {
051: TemplateSet foreignTS = tm.getTemplateSet("default");
052: if (foreignTS == null) {
053: Server.log(this , "No default-templateset present",
054: Server.MSG_ERROR, Server.LVL_MAJOR);
055: } else {
056: props = foreignTS.getMessageTemplateSet();
057: msgSetPresent = true;
058: }
059: }
060: }
061: if (!"admin".equals(name)) { // admin-templates are different
062: if (!checkTemplateCompleteness(templatesNeeded))
063: return;
064: if (!msgSetPresent) {
065: Server
066: .log(
067: this ,
068: "TemplateSet.construct: Templateset has no message.set! Ignoring.",
069: Server.MSG_STATE, Server.LVL_MAJOR);
070: this .isValide = false;
071: return;
072: }
073: } else {
074: if (!checkTemplateCompleteness(adminTemplates)) {
075: Server
076: .log(
077: this ,
078: "TemplateSet.construct: Admin-Templateset doesn't have a header and wount work without it",
079: Server.MSG_STATE, Server.LVL_MAJOR);
080: return;
081: }
082: }
083: this .isValide = true;
084: }
085:
086: private Hashtable createTemplates(File dir) {
087: Hashtable tempTable = new Hashtable();
088: File tFiles[] = dir.listFiles();
089: for (int i = 0; i < tFiles.length; i++) {
090: if (!tFiles[i].isFile())
091: continue;
092: if (tFiles[i].getName().equalsIgnoreCase("message.set"))
093: try {
094: readMessageSet(tFiles[i]);
095: continue;
096: } catch (FileNotFoundException fnfe) {
097: // doesn't happen
098: } catch (IOException ioe) {
099: Server.debug(this , "message.set of " + name
100: + " caused exception", ioe,
101: Server.MSG_ERROR, Server.LVL_MAJOR);
102: }
103: try {
104: Template t = new Template(tFiles[i], this );
105: if (t.isValide())
106: tempTable.put(t.getName(), t);
107: } catch (IOException ioe) {
108: Server.debug(this ,
109: "constructing Template caused exception for file "
110: + tFiles[i].getName(), ioe,
111: Server.MSG_ERROR, Server.LVL_MAJOR);
112: }
113: }
114: if (!msgSetPresent) {
115: if (name.equals("default")) {
116: Server
117: .log(
118: this ,
119: "Default-templateset doesn't have a message.set-file",
120: Server.MSG_ERROR, Server.LVL_HALT);
121: } else {
122: TemplateSet foreignTS = tm.getTemplateSet("default");
123: if (foreignTS == null) {
124: Server.log(this , "No default-templateset present",
125: Server.MSG_ERROR, Server.LVL_MAJOR);
126: } else {
127: props = foreignTS.getMessageTemplateSet();
128: msgSetPresent = true;
129: }
130: }
131: msgSet = null;
132: FileMonitor.getFileMonitor().removeMonitor(this );
133: } else {
134: FileMonitor.getFileMonitor().addReloadable(this );
135: }
136: return tempTable;
137: }
138:
139: public void reload(File dir) {
140: createTemplates(dir);
141: }
142:
143: public String getName() {
144: return name;
145: }
146:
147: public Template getTemplate(String tName) {
148: return ((Template) tpl.get(tName));
149: }
150:
151: public void removeTemplate(Template t) {
152: tpl.remove(t.getName());
153: }
154:
155: public void addTemplate(Template t) {
156: tpl.put(t.getName(), t);
157: }
158:
159: public String getMessageTemplate(String msgTplName) {
160: return props.getProperty(msgTplName);
161: }
162:
163: public Properties getMessageTemplateSet() {
164: return props;
165: }
166:
167: public boolean isValide() {
168: return isValide;
169: }
170:
171: public void readMessageSet(File f) throws FileNotFoundException,
172: IOException {
173: // we have found the messageset
174: msgSetPresent = true;
175: msgSet = f;
176: lastModified = msgSet.lastModified();
177: FileInputStream fis = new FileInputStream(f);
178: if (props == null)
179: props = new Properties();
180: props.load(fis);
181: fis.close();
182: Properties tProps = (Properties) props.clone();
183:
184: for (int i = 0; i < neededMessageTemplates.length; i++) {
185: if (props.get(neededMessageTemplates[i]) == null) {
186: Server.log(this , "readMessageSet [" + name
187: + "]: Message-template '"
188: + neededMessageTemplates[i]
189: + "' is not present", Server.MSG_STATE,
190: Server.LVL_VERBOSE);
191: }
192: tProps.remove(neededMessageTemplates[i]);
193: }
194: for (Enumeration ig = tProps.keys(); ig.hasMoreElements();) {
195: String param = ig.nextElement().toString();
196: int pos = param.indexOf(".");
197:
198: if (pos > 0) {
199: String p = param.substring(0, pos);
200: if (Ignore(p))
201: tProps.remove(param);
202: }
203:
204: }
205: for (Enumeration e = tProps.keys(); e.hasMoreElements();) {
206: Server.log(this , "readMessageSet [" + name
207: + "]: Unknown message-template found: "
208: + e.nextElement().toString(), Server.MSG_STATE,
209: Server.LVL_VERBOSE);
210: }
211: }
212:
213: /* INTERFACE RELOADABLE */
214: public long lastModified() {
215: return lastModified;
216: }
217:
218: public void changed() {
219: try {
220: FileInputStream fis = new FileInputStream(msgSet);
221: Properties tprop = new Properties();
222: tprop.load(fis);
223: fis.close();
224: props = tprop;
225: lastModified = msgSet.lastModified();
226: Server.log(this , "reload: reloaded messagetemplates",
227: Server.MSG_STATE, Server.LVL_MINOR);
228: } catch (Exception e) {
229: Server.debug(this , "reload: ", e, Server.MSG_ERROR,
230: Server.LVL_MAJOR);
231: }
232: }
233:
234: public void removed() {
235: if (name.equals("default")) {
236: Server
237: .log(
238: this ,
239: "WARNING: message.set has been removed for DEFAULT-layout! Default-Layout must have one!",
240: Server.MSG_ERROR, Server.LVL_MAJOR);
241: } else {
242: Server.log(this ,
243: "WARNING: message.set has been removed for layout "
244: + name, Server.MSG_ERROR, Server.LVL_MINOR);
245: }
246: TemplateSet foreignTS = tm.getTemplateSet("default");
247: if (foreignTS == null) {
248: Server
249: .log(
250: this ,
251: "No default-templateset present making it impossible to fall back to the default-layout's message.set. Keeping the old messag.set",
252: Server.MSG_ERROR, Server.LVL_MAJOR);
253: } else {
254: props = foreignTS.getMessageTemplateSet();
255: }
256: msgSetPresent = false;
257: }
258:
259: public boolean filePresent() {
260: return msgSetPresent;
261: }
262:
263: public void created() {
264: changed();
265: msgSetPresent = true;
266: }
267:
268: public File getFile() {
269: return msgSet;
270: }
271:
272: private boolean checkTemplateCompleteness(String[] templates) {
273: for (int i = 0; i < templates.length; i++) {
274: if (tpl.containsKey(templates[i]))
275: continue;
276: this .isValide = false;
277: return false;
278: }
279: return true;
280: }
281:
282: private boolean Ignore(String param) {
283: if (param.equals("constant"))
284: return true;
285: return false;
286: }
287:
288: private volatile String strgVal;
289:
290: public String toString() {
291: if (strgVal == null) {
292: StringBuffer sb = new StringBuffer("[TemplateSet: ");
293: sb.append(this .name);
294: sb.append("]");
295: strgVal = sb.toString();
296: }
297: return strgVal;
298: }
299:
300: public boolean equals(Object obj) {
301: if (obj == null)
302: return false;
303: if (!(obj instanceof TemplateSet))
304: return false;
305: if (!this .name.equals(((TemplateSet) obj).name))
306: return false;
307: return true;
308: }
309:
310: public int hashCode() {
311: if (hashCode != Integer.MIN_VALUE)
312: return hashCode;
313: hashCode = ("TemplateSet" + name).hashCode();
314: return (hashCode);
315: }
316:
317: private static final String templatesNeeded[] = { "start",
318: "welcome", "login_missing", "login_failed", "not_found" };
319:
320: private static final String adminTemplates[] = { "admin_header" };
321:
322: public static final String neededMessageTemplates[] = {
323: "error.group.notExisting",
324: "error.user.notOnServer.singular",
325: "error.user.notOnServer.plural", "error.a.noLongerValid",
326: "error.me.noArg", "error.m.cantHearYou", "error.ban.noArg",
327: "error.ban.noRight", "error.uban.noArg",
328: "error.uban.noRight", "error.col.startingGroup",
329: "error.col.noRight", "error.col.wrongCode",
330: "error.col.lockedColor", "error.col.tooOften",
331: "error.td.noArg", "error.td.noRight", "error.td.wrong",
332: "error.td.toomany", "error.ig.noArg", "error.i.noRight",
333: "error.i.noArg", "error.i.alreadyInvited",
334: "error.ia.all.noRight", "error.ia.noRight",
335: "error.ia.inviteStartGroup", "error.j.noArg",
336: "error.j.alreadyHere", "error.j.banned",
337: "error.j.noRightToOpen", "error.j.closed",
338: "error.j.noRight", "error.jclosed.noRight",
339: "error.jclosed.groupNotExisting", "error.ju.alreadyHere",
340: "error.ju.noArg", "error.k.noRight",
341: "error.k.noGroupRight", "error.kc.noroom",
342: "error.kh.noRight", "error.fl.nofriends",
343: "error.f.noFriendOnline", "error.wban.noRight",
344: "error.wban.nobodyBanned", "error.vip.noVipOnline",
345: "error.l.noRight", "error.ul.noRight", "error.m.noArg",
346: "error.m.noMessage", "error.m.vip.noRight",
347: "error.moderated.timelock", "error.gag.noRight",
348: "error.gag.noArg", "error.gag.protected", "error.aq.noArg",
349: "error.rig.noArg", "error.rsu.noArg", "error.rsu.noRight",
350: "error.su.noArg", "error.su.noRight",
351: "error.su.tooManyForStartgroup", "error.sepa.noArg",
352: "error.sepa.noRight", "error.sepa.l.noRight",
353: "error.sepa.alreadyExists", "error.t.noRight",
354: "error.s.noArg", "error.ip.noArg", "error.w.nobodyHere",
355: "error.th.noArg", "error.sys.noArg", "error.user.punished",
356: "message.send", "message.send.moderated",
357: "message.send.moderated.personal", "message.a",
358: "message.a.personal", "message.away.on",
359: "message.away.off", "message.col", "message.c",
360: "message.me", "message.ban.personal", "message.ban.plural",
361: "message.ban.singular", "message.ban.confirm.plural",
362: "message.ban.confirm.singular", "message.uban.personal",
363: "message.uban.plural", "message.uban.singular",
364: "message.uban.confirm.plural",
365: "message.uban.confirm.singular",
366: "error.uban.notOnList.singular",
367: "error.uban.notOnList.plural", "message.td",
368: "message.ig.plural", "message.ig.singular",
369: "message.i.personal", "message.i.plural",
370: "message.i.singular", "message.ia.all", "message.ia.group",
371: "message.j.created", "message.j", "message.jclosed",
372: "message.k.destination.singular",
373: "message.k.confirm.singular", "message.k.singular",
374: "message.k.destination.plural", "message.k.confirm.plural",
375: "message.k.plural", "message.k.personal",
376: "message.kh.singular", "message.kh.confirm.singular",
377: "message.kh.plural", "message.kh.confirm.plural",
378: "message.kh.personal", "message.kh.godinfo",
379: "message.kc.personal", "message.kc.destination.singular",
380: "message.kc.confirm.singular", "message.kc.singular",
381: "message.kc.destination.plural",
382: "message.kc.confirm.plural", "message.kc.plural",
383: "message.kc.godinfo", "message.f.headline",
384: "message.f.isOnline", "message.f.joined", "message.f",
385: "message.f.count", "message.wban", "message.wc.headline",
386: "message.m.vip", "message.m.vip.confirm",
387: "message.vip.singular", "message.vip.plural", "message.l",
388: "message.ul", "message.mycol", "message.m",
389: "message.m.away", "message.m.confirm",
390: "message.gag.singular", "message.gag.plural",
391: "message.gag.confirm.singular",
392: "message.gag.confirm.plural", "message.aq", "message.q",
393: "message.rig.singular", "message.rig.plural",
394: "message.rsu.personal", "message.rsu.singular",
395: "message.rsu.plural", "message.rsu.confirm.singular",
396: "message.rsu.confirm.plural", "message.su.personal",
397: "message.su.singular", "message.su.plural",
398: "message.su.confirm.singular", "message.su.confirm.plural",
399: "message.sepa", "message.sepa.confirm", "message.s",
400: "message.ip", "message.time", "message.user.detail",
401: "message.t", "message.t.removed", "message.th",
402: "message.sys", "message.fl.headline",
403: "message.fl.entry.offline", "message.fl.entry.online",
404: "message.fl.count", "message.user.short",
405: "message.user.short.seperator", "message.user.overview",
406: "message.user.flooded", "message.user.tooled",
407: "message.user.leaving.group", "message.user.join.group",
408: "message.user.join.closedGroup",
409: "message.user.join.server",
410: "message.user.join.server.personal", "message.user.vip",
411: "message.server.shutdown", "message.wc.underline",
412: "message.softClose", "list.users", "constant.userListItem",
413: "status.showtime", "status.showtime.timeformat",
414: "constant.defaultColor", "constant.lockedGroup",
415: "constant.openGroup", "constant.linkedName",
416: "error.ack.groupNotModerated", "error.ack.noArg",
417: "error.ack.noMessage", "error.ack.userNotInGroup",
418: "error.i.alreadyHere", "error.rgag.noArg",
419: "error.rgag.noRight", "error.sepa.alreadyHere",
420: "message.ack", "message.gag.personal",
421: "message.rgag.personal", "message.rgag.confirm.plural",
422: "message.rgag.confirm.singular", "message.rgag.plural",
423: "message.rgag.singular", "message.user.leaving.server",
424: "message.user.leaving.server.kicked", "error.raq.noRight",
425: "message.raq", "error.fcol.noRight", "error.fcol.noArg",
426: "error.fcol.noUser", "message.fcol.singular",
427: "message.fcol.plural", "message.fcol.confirm.singular",
428: "message.fcol.confirm.plural", "message.fcol.personal",
429: "error.noRight.isAdmin", "error.noRight.isVip",
430: "error.noRight.noSuVipAdmin", "error.noRight.noVipAdmin",
431: "error.noRight.noAdmin", "error.noRight.noModAdmin",
432: "error.noRight.noMod", "error.noRight.deactivated",
433: "error.noRight.isSuForbiddenMembership",
434: "error.mass.noRight.noVipAdmin", "error.rc.noArg",
435: "error.rc.userNotFound", "error.rc.rightNotFound",
436: "error.rc.notRight", "rc.rightAssigned", "rc.rightRevoked",
437: "rc.newAssignedRight", "rc.newRevokedRight",
438: "rc.rightsReset", "rc.newResetRight" };
439: }
|