001: /*
002: * This file is part of DrFTPD, Distributed FTP Daemon.
003: *
004: * DrFTPD is free software; you can redistribute it and/or modify
005: * it under the terms of the GNU General Public License as published by
006: * the Free Software Foundation; either version 2 of the License, or
007: * (at your option) any later version.
008: *
009: * DrFTPD 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 DrFTPD; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: */
018: package org.drftpd;
019:
020: import java.io.FileNotFoundException;
021: import java.io.IOException;
022: import java.lang.reflect.Constructor;
023: import java.util.ArrayList;
024: import java.util.Iterator;
025: import java.util.List;
026: import java.util.Properties;
027: import java.util.Timer;
028:
029: import net.sf.drftpd.FatalException;
030: import net.sf.drftpd.ObjectNotFoundException;
031: import net.sf.drftpd.event.Event;
032: import net.sf.drftpd.event.FtpListener;
033: import net.sf.drftpd.event.MessageEvent;
034: import net.sf.drftpd.master.SlaveFileException;
035: import net.sf.drftpd.master.config.ConfigInterface;
036: import net.sf.drftpd.master.config.FtpConfig;
037: import net.sf.drftpd.master.config.ZipscriptConfig;
038: import net.sf.drftpd.mirroring.JobManager;
039: import net.sf.drftpd.util.PortRange;
040:
041: import org.apache.log4j.Logger;
042: import org.drftpd.master.ConnectionManager;
043: import org.drftpd.master.SlaveManager;
044: import org.drftpd.remotefile.LinkedRemoteFile;
045: import org.drftpd.remotefile.LinkedRemoteFileInterface;
046: import org.drftpd.remotefile.MLSTSerialize;
047: import org.drftpd.sections.SectionManagerInterface;
048: import org.drftpd.slaveselection.SlaveSelectionManagerInterface;
049: import org.drftpd.usermanager.AbstractUserManager;
050: import org.drftpd.usermanager.UserManager;
051:
052: /**
053: * @author mog
054: * @version $Id: GlobalContext.java 1312 2005-10-14 18:38:37Z zubov $
055: */
056: /**
057: * @author zubov
058: *
059: */
060: public class GlobalContext {
061: private static final Logger logger = Logger
062: .getLogger(GlobalContext.class);
063: protected ConnectionManager _cm;
064: protected ConfigInterface _config;
065: protected ZipscriptConfig _zsConfig;
066: private ArrayList<FtpListener> _ftpListeners = new ArrayList<FtpListener>();
067: protected JobManager _jm;
068: protected LinkedRemoteFileInterface _root;
069: protected SectionManagerInterface _sections;
070: private String _shutdownMessage = null;
071: protected SlaveManager _slaveManager;
072: protected AbstractUserManager _usermanager;
073: private Timer _timer = new Timer("GlobalContextTimer");
074: protected SlaveSelectionManagerInterface _slaveSelectionManager;
075: private String _cfgFileName;
076:
077: protected GlobalContext() {
078: }
079:
080: public void reloadFtpConfig() throws IOException {
081: _config = new FtpConfig(_cfgFileName, this );
082: _zsConfig = new ZipscriptConfig(this );
083: }
084:
085: public GlobalContext(Properties cfg, String cfgFileName,
086: ConnectionManager cm) throws SlaveFileException {
087: _cfgFileName = cfgFileName;
088: _cm = cm;
089: _cm.setGlobalContext(this );
090: loadUserManager(cfg, cfgFileName);
091:
092: try {
093: _config = new FtpConfig(cfg, cfgFileName, this );
094: } catch (Throwable ex) {
095: throw new FatalException(ex);
096: }
097:
098: try {
099: _zsConfig = new ZipscriptConfig(this );
100: } catch (Throwable ex) {
101: throw new FatalException(ex);
102: }
103:
104: loadSlaveManager(cfg);
105: loadRSlavesAndRoot();
106: listenForSlaves();
107: loadJobManager();
108: getJobManager().startJobs();
109: loadSlaveSelectionManager(cfg);
110: loadSectionManager(cfg);
111: loadPlugins(cfg);
112: }
113:
114: private void loadJobManager() {
115: _jm = new JobManager(this );
116: }
117:
118: /**
119: *
120: */
121: private void loadSlaveSelectionManager(Properties cfg) {
122: try {
123: Constructor c = Class
124: .forName(
125: cfg
126: .getProperty("slaveselection",
127: "org.drftpd.slaveselection.def.DefaultSlaveSelectionManager"))
128: .getConstructor(new Class[] { GlobalContext.class });
129: _slaveSelectionManager = (SlaveSelectionManagerInterface) c
130: .newInstance(new Object[] { this });
131: } catch (Exception e) {
132: if (e instanceof RuntimeException) {
133: throw (RuntimeException) e;
134: }
135:
136: throw new FatalException(e);
137: }
138: }
139:
140: /**
141: * Calls init(this) on the argument
142: */
143: public synchronized void addFtpListener(FtpListener listener) {
144: listener.init(this );
145: _ftpListeners.add(listener);
146: }
147:
148: public synchronized void delFtpListener(FtpListener listener) {
149: _ftpListeners.remove(listener);
150: }
151:
152: public void dispatchFtpEvent(Event event) {
153: logger.debug("Dispatching " + event + " to "
154: + getFtpListeners());
155:
156: for (FtpListener handler : getFtpListeners()) {
157: try {
158: handler.actionPerformed(event);
159: } catch (RuntimeException e) {
160: logger.warn("RuntimeException dispatching event", e);
161: }
162: }
163: }
164:
165: public ConfigInterface getConfig() {
166: assert _config != null;
167: return _config;
168: }
169:
170: public ZipscriptConfig getZsConfig() {
171: assert _zsConfig != null;
172: return _zsConfig;
173: }
174:
175: public ConnectionManager getConnectionManager() {
176: assert _cm != null;
177: return _cm;
178: }
179:
180: public List<FtpListener> getFtpListeners() {
181: return new ArrayList<FtpListener>(_ftpListeners);
182: }
183:
184: /**
185: * JobManager is now loaded as an integral part of the daemon
186: * If no Jobs are sent, it utilizes very little resources
187: */
188: public JobManager getJobManager() {
189: return _jm;
190: }
191:
192: public LinkedRemoteFileInterface getRoot() {
193: if (_root == null) {
194: throw new NullPointerException();
195: }
196:
197: return _root;
198: }
199:
200: public SectionManagerInterface getSectionManager() {
201: if (_sections == null) {
202: throw new NullPointerException();
203: }
204:
205: return _sections;
206: }
207:
208: public String getShutdownMessage() {
209: return _shutdownMessage;
210: }
211:
212: public SlaveManager getSlaveManager() {
213: if (_slaveManager == null) {
214: throw new NullPointerException();
215: }
216:
217: return _slaveManager;
218: }
219:
220: public UserManager getUserManager() {
221: if (_usermanager == null) {
222: throw new NullPointerException();
223: }
224:
225: return _usermanager;
226: }
227:
228: public boolean isJobManagerLoaded() {
229: return (_jm != null);
230: }
231:
232: public boolean isShutdown() {
233: return _shutdownMessage != null;
234: }
235:
236: protected void loadPlugins(Properties cfg) {
237: for (int i = 1;; i++) {
238: String classname = cfg.getProperty("plugins." + i);
239:
240: if (classname == null) {
241: break;
242: }
243:
244: try {
245: FtpListener ftpListener = (FtpListener) Class.forName(
246: classname).newInstance();
247: addFtpListener(ftpListener);
248: } catch (Exception e) {
249: throw new FatalException("Error loading plugins", e);
250: }
251: }
252: }
253:
254: /**
255: * Depends on slavemanager being loaded.
256: *
257: */
258: private void loadRSlavesAndRoot() {
259: try {
260: List rslaves = _slaveManager.getSlaves();
261: logger.info("Loading files.mlst");
262: _root = MLSTSerialize.loadMLSTFileDatabase(rslaves, _cm);
263: } catch (FileNotFoundException e) {
264: logger
265: .info("files.mlst not found, creating a new filelist");
266: _root = new LinkedRemoteFile(getConfig());
267: } catch (IOException e) {
268: throw new FatalException(e);
269: }
270: }
271:
272: // depends on having getRoot() working
273: private void loadSectionManager(Properties cfg) {
274: try {
275: Class cl = Class.forName(cfg.getProperty("sectionmanager",
276: "org.drftpd.sections.def.SectionManager"));
277: Constructor c = cl
278: .getConstructor(new Class[] { ConnectionManager.class });
279: _sections = (SectionManagerInterface) c
280: .newInstance(new Object[] { _cm });
281: } catch (Exception e) {
282: throw new FatalException(e);
283: }
284: }
285:
286: /**
287: * Depends on root loaded if any slaves connect early.
288: */
289: private void loadSlaveManager(Properties cfg)
290: throws SlaveFileException {
291: /** register slavemanager **/
292: _slaveManager = new SlaveManager(cfg, this );
293: }
294:
295: private void listenForSlaves() {
296: new Thread(_slaveManager, "Listening for slave connections - "
297: + _slaveManager.toString()).start();
298: }
299:
300: protected void loadUserManager(Properties cfg, String cfgFileName) {
301: try {
302: _usermanager = (AbstractUserManager) Class.forName(
303: PropertyHelper.getProperty(cfg,
304: "master.usermanager")).newInstance();
305:
306: // if the below method is not run, JSXUserManager fails when trying to do a reset() on the user logging in
307: _usermanager.init(this );
308: } catch (Exception e) {
309: throw new FatalException(
310: "Cannot create instance of usermanager, check master.usermanager in "
311: + cfgFileName, e);
312: }
313: }
314:
315: /**
316: * Doesn't close connections like ConnectionManager.close() does
317: * ConnectionManager.close() calls this method.
318: * @see org.drftpd.master.ConnectionManager#shutdown(String)
319: */
320: public void shutdown(String message) {
321: _shutdownMessage = message;
322: dispatchFtpEvent(new MessageEvent("SHUTDOWN", message));
323: getConnectionManager().shutdownPrivate(message);
324: }
325:
326: public Timer getTimer() {
327: return _timer;
328: }
329:
330: public SlaveSelectionManagerInterface getSlaveSelectionManager() {
331: return _slaveSelectionManager;
332: }
333:
334: public PortRange getPortRange() {
335: return getConfig().getPortRange();
336: }
337:
338: public FtpListener getFtpListener(Class clazz)
339: throws ObjectNotFoundException {
340: for (FtpListener listener : new ArrayList<FtpListener>(
341: getFtpListeners())) {
342:
343: if (clazz.isInstance(listener)) {
344: return listener;
345: }
346: }
347:
348: throw new ObjectNotFoundException();
349: }
350: }
|