1 /************************************************************************
2 * Copyright (c) 2000-2006 The Apache Software Foundation. *
3 * All rights reserved. *
4 * ------------------------------------------------------------------- *
5 * Licensed under the Apache License, Version 2.0 (the "License"); you *
6 * may not use this file except in compliance with the License. You *
7 * may obtain a copy of the License at: *
8 * *
9 * http://www.apache.org/licenses/LICENSE-2.0 *
10 * *
11 * Unless required by applicable law or agreed to in writing, software *
12 * distributed under the License is distributed on an "AS IS" BASIS, *
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or *
14 * implied. See the License for the specific language governing *
15 * permissions and limitations under the License. *
16 ***********************************************************************/
17
18 package org.apache.james.nntpserver;
19
20 import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
21 import org.apache.avalon.excalibur.pool.DefaultPool;
22 import org.apache.avalon.excalibur.pool.HardResourceLimitingPool;
23 import org.apache.avalon.excalibur.pool.ObjectFactory;
24 import org.apache.avalon.excalibur.pool.Pool;
25 import org.apache.avalon.excalibur.pool.Poolable;
26 import org.apache.avalon.framework.activity.Initializable;
27 import org.apache.avalon.framework.configuration.Configuration;
28 import org.apache.avalon.framework.configuration.ConfigurationException;
29 import org.apache.avalon.framework.logger.LogEnabled;
30 import org.apache.avalon.framework.service.ServiceException;
31 import org.apache.avalon.framework.service.ServiceManager;
32
33 import org.apache.james.core.AbstractJamesService;
34 import org.apache.james.nntpserver.repository.NNTPRepository;
35 import org.apache.james.services.UsersRepository;
36 import org.apache.james.util.watchdog.Watchdog;
37 import org.apache.james.util.watchdog.WatchdogFactory;
38
39 /***
40 * NNTP Server
41 *
42 */
43 public class NNTPServer extends AbstractJamesService implements NNTPServerMBean {
44
45 /***
46 * Whether authentication is required to access this NNTP server
47 */
48 private boolean authRequired = false;
49
50 /***
51 * The repository that stores the news articles for this NNTP server.
52 */
53 private NNTPRepository repo;
54
55 /***
56 * The repository that stores the local users. Used for authentication.
57 */
58 private UsersRepository userRepository = null;
59
60 /***
61 * The pool used to provide NNTP Handler objects
62 */
63 private Pool theHandlerPool = null;
64
65 /***
66 * The pool used to provide NNTP Handler objects
67 */
68 private ObjectFactory theHandlerFactory = new NNTPHandlerFactory();
69
70 /***
71 * The factory used to generate Watchdog objects
72 */
73 private WatchdogFactory theWatchdogFactory;
74
75 /***
76 * The configuration data to be passed to the handler
77 */
78 private NNTPHandlerConfigurationData theConfigData
79 = new NNTPHandlerConfigurationDataImpl();
80
81 /***
82 * @see org.apache.avalon.framework.service.Serviceable#service(ServiceManager)
83 */
84 public void service( final ServiceManager componentManager )
85 throws ServiceException {
86 super.service(componentManager);
87 userRepository = (UsersRepository)componentManager.lookup(UsersRepository.ROLE);
88
89 repo = (NNTPRepository)componentManager
90 .lookup("org.apache.james.nntpserver.repository.NNTPRepository");
91
92 }
93
94 /***
95 * @see org.apache.avalon.framework.configuration.Configurable#configure(Configuration)
96 */
97 public void configure(final Configuration configuration) throws ConfigurationException {
98 super.configure(configuration);
99 if (isEnabled()) {
100 Configuration handlerConfiguration = configuration.getChild("handler");
101 authRequired =
102 handlerConfiguration.getChild("authRequired").getValueAsBoolean(false);
103 if (getLogger().isDebugEnabled()) {
104 if (authRequired) {
105 getLogger().debug("NNTP Server requires authentication.");
106 } else {
107 getLogger().debug("NNTP Server doesn't require authentication.");
108 }
109 }
110 }
111 }
112
113 /***
114 * @see org.apache.avalon.framework.activity.Initializable#initialize()
115 */
116 public void initialize() throws Exception {
117 super.initialize();
118 if (!isEnabled()) {
119 return;
120 }
121
122 if (connectionLimit != null) {
123 theHandlerPool = new HardResourceLimitingPool(theHandlerFactory, 5, connectionLimit.intValue());
124 getLogger().debug("Using a bounded pool for NNTP handlers with upper limit " + connectionLimit.intValue());
125 } else {
126
127
128 theHandlerPool = new DefaultPool(theHandlerFactory, null, 5, 30);
129 getLogger().debug("Using an unbounded pool for NNTP handlers.");
130 }
131 if (theHandlerPool instanceof LogEnabled) {
132 ((LogEnabled)theHandlerPool).enableLogging(getLogger());
133 }
134 if (theHandlerPool instanceof Initializable) {
135 ((Initializable)theHandlerPool).initialize();
136 }
137
138 theWatchdogFactory = getWatchdogFactory();
139 }
140
141 /***
142 * @see org.apache.james.core.AbstractJamesService#getDefaultPort()
143 */
144 protected int getDefaultPort() {
145 return 119;
146 }
147
148 /***
149 * @see org.apache.james.core.AbstractJamesService#getServiceType()
150 */
151 public String getServiceType() {
152 return "NNTP Service";
153 }
154
155 /***
156 * @see org.apache.avalon.cornerstone.services.connection.AbstractHandlerFactory#newHandler()
157 */
158 protected ConnectionHandler newHandler()
159 throws Exception {
160 NNTPHandler theHandler = (NNTPHandler)theHandlerPool.get();
161
162 Watchdog theWatchdog = theWatchdogFactory.getWatchdog(theHandler.getWatchdogTarget());
163
164 theHandler.setConfigurationData(theConfigData);
165 theHandler.setWatchdog(theWatchdog);
166 return theHandler;
167 }
168
169 /***
170 * @see org.apache.avalon.cornerstone.services.connection.ConnectionHandlerFactory#releaseConnectionHandler(ConnectionHandler)
171 */
172 public void releaseConnectionHandler( ConnectionHandler connectionHandler ) {
173 if (!(connectionHandler instanceof NNTPHandler)) {
174 throw new IllegalArgumentException("Attempted to return non-NNTPHandler to pool.");
175 }
176 theHandlerPool.put((Poolable)connectionHandler);
177 }
178
179 /***
180 * The factory for producing handlers.
181 */
182 private static class NNTPHandlerFactory
183 implements ObjectFactory {
184
185 /***
186 * @see org.apache.avalon.excalibur.pool.ObjectFactory#newInstance()
187 */
188 public Object newInstance() throws Exception {
189 return new NNTPHandler();
190 }
191
192 /***
193 * @see org.apache.avalon.excalibur.pool.ObjectFactory#getCreatedClass()
194 */
195 public Class getCreatedClass() {
196 return NNTPHandler.class;
197 }
198
199 /***
200 * @see org.apache.avalon.excalibur.pool.ObjectFactory#decommision(Object)
201 */
202 public void decommission( Object object ) throws Exception {
203 return;
204 }
205 }
206
207 /***
208 * A class to provide NNTP handler configuration to the handlers
209 */
210 private class NNTPHandlerConfigurationDataImpl
211 implements NNTPHandlerConfigurationData {
212
213 /***
214 * @see org.apache.james.smtpserver.NNTPHandlerConfigurationData#getHelloName()
215 */
216 public String getHelloName() {
217 return NNTPServer.this.helloName;
218 }
219
220 /***
221 * @see org.apache.james.smtpserver.NNTPHandlerConfigurationData#isAuthRequired()
222 */
223 public boolean isAuthRequired() {
224 return NNTPServer.this.authRequired;
225 }
226
227 /***
228 * @see org.apache.james.smtpserver.NNTPHandlerConfigurationData#getUsersRepository()
229 */
230 public UsersRepository getUsersRepository() {
231 return NNTPServer.this.userRepository;
232 }
233
234 /***
235 * @see org.apache.james.smtpserver.NNTPHandlerConfigurationData#getNNTPRepository()
236 */
237 public NNTPRepository getNNTPRepository() {
238 return NNTPServer.this.repo;
239 }
240
241 }
242 }