1 17 18 package org.apache.james.core; 19 20 import java.io.*; 21 import java.net.*; 22 23 import org.apache.avalon.framework.logger.*; 24 import org.apache.avalon.framework.component.*; 25 import org.apache.avalon.framework.configuration.*; 26 import org.apache.avalon.framework.activity.*; 27 28 import org.apache.avalon.excalibur.thread.ThreadPool; 29 import org.apache.avalon.cornerstone.services.threads.ThreadManager; 30 31 import org.apache.avalon.cornerstone.services.connection.AbstractHandlerFactory; 32 import org.apache.avalon.cornerstone.services.connection.ConnectionHandler; 33 import org.apache.avalon.cornerstone.services.connection.ConnectionHandlerFactory; 34 import org.apache.avalon.cornerstone.services.sockets.ServerSocketFactory; 35 import org.apache.avalon.cornerstone.services.sockets.SocketManager; 36 37 import org.apache.james.services.JamesConnectionManager; 38 import org.apache.james.util.watchdog.ThreadPerWatchdogFactory; 39 import org.apache.james.util.watchdog.Watchdog; 40 import org.apache.james.util.watchdog.WatchdogFactory; 41 42 47 public abstract class AbstractJamesService extends AbstractHandlerFactory 48 implements Component, Composable, Configurable, 49 Disposable, Initializable, ConnectionHandlerFactory { 50 51 54 protected static final int DEFAULT_TIMEOUT = 5* 60 * 1000; 55 56 59 protected static final String TIMEOUT_NAME = "connectiontimeout"; 60 61 64 protected static final int DEFAULT_BACKLOG = 5; 65 66 69 protected static final String BACKLOG_NAME = "connectionBacklog"; 70 71 74 public static final String HELLO_NAME = "helloName"; 75 76 79 private JamesConnectionManager connectionManager; 80 81 85 protected String threadGroup; 86 87 91 protected ThreadPool threadPool = null; 92 93 96 protected String serverSocketType = "plain"; 97 98 101 protected int port = -1; 102 103 107 protected InetAddress bindTo = null; 108 109 112 protected ServerSocket serverSocket; 113 114 119 protected String connectionName; 120 121 124 protected Integer connectionLimit; 125 126 130 protected int timeout; 131 132 135 protected int backlog; 136 137 140 protected String helloName; 141 142 145 private ComponentManager compMgr; 146 147 150 private volatile boolean enabled; 151 152 155 public void compose(ComponentManager comp) throws ComponentException { 156 super.compose(comp); 157 compMgr = comp; 158 connectionManager = (JamesConnectionManager) compMgr.lookup(JamesConnectionManager.ROLE); 159 } 160 161 164 public void configure(Configuration conf) throws ConfigurationException { 165 enabled = conf.getAttributeAsBoolean("enabled", true); 166 if (!enabled) { 167 getLogger().info(getServiceType() + " disabled by configuration"); 168 return; 169 } 170 171 Configuration handlerConfiguration = conf.getChild("handler"); 172 173 super.configure(handlerConfiguration); 181 182 port = conf.getChild("port").getValueAsInteger(getDefaultPort()); 183 184 Configuration serverSocketTypeConf = conf.getChild("serverSocketType", false); 185 String confSocketType = null; 186 if (serverSocketTypeConf != null ) { 187 confSocketType = serverSocketTypeConf.getValue(); 188 } 189 190 if (confSocketType == null) { 191 final boolean useTLS = conf.getChild("useTLS").getValueAsBoolean(isDefaultTLSEnabled()); 196 if (useTLS) { 197 serverSocketType = "ssl"; 198 } 199 } else { 200 serverSocketType = confSocketType; 201 } 202 203 StringBuffer infoBuffer; 204 threadGroup = conf.getChild("threadGroup").getValue(null); 205 if (threadGroup != null) { 206 infoBuffer = 207 new StringBuffer (64) 208 .append(getServiceType()) 209 .append(" uses thread group: ") 210 .append(threadGroup); 211 getLogger().info(infoBuffer.toString()); 212 } 213 else { 214 getLogger().info(getServiceType() + " uses default thread group."); 215 } 216 217 try { 218 final String bindAddress = conf.getChild("bind").getValue(null); 219 if( null != bindAddress ) { 220 bindTo = InetAddress.getByName(bindAddress); 221 infoBuffer = 222 new StringBuffer (64) 223 .append(getServiceType()) 224 .append(" bound to: ") 225 .append(bindTo); 226 getLogger().info(infoBuffer.toString()); 227 } 228 } 229 catch( final UnknownHostException unhe ) { 230 throw new ConfigurationException( "Malformed bind parameter in configuration of service " + getServiceType(), unhe ); 231 } 232 233 String hostName = null; 234 try { 235 hostName = InetAddress.getLocalHost().getHostName(); 236 } catch (UnknownHostException ue) { 237 hostName = "localhost"; 238 } 239 240 infoBuffer = 241 new StringBuffer (64) 242 .append(getServiceType()) 243 .append(" is running on: ") 244 .append(hostName); 245 getLogger().info(infoBuffer.toString()); 246 247 Configuration helloConf = handlerConfiguration.getChild(HELLO_NAME); 248 boolean autodetect = helloConf.getAttributeAsBoolean("autodetect", true); 249 if (autodetect) { 250 helloName = hostName; 251 } else { 252 helloName = helloConf.getValue("localhost"); 253 } 254 infoBuffer = 255 new StringBuffer (64) 256 .append(getServiceType()) 257 .append(" handler hello name is: ") 258 .append(helloName); 259 getLogger().info(infoBuffer.toString()); 260 261 timeout = handlerConfiguration.getChild(TIMEOUT_NAME).getValueAsInteger(DEFAULT_TIMEOUT); 262 263 infoBuffer = 264 new StringBuffer (64) 265 .append(getServiceType()) 266 .append(" handler connection timeout is: ") 267 .append(timeout); 268 getLogger().info(infoBuffer.toString()); 269 270 backlog = conf.getChild(BACKLOG_NAME).getValueAsInteger(DEFAULT_BACKLOG); 271 272 infoBuffer = 273 new StringBuffer (64) 274 .append(getServiceType()) 275 .append(" connection backlog is: ") 276 .append(backlog); 277 getLogger().info(infoBuffer.toString()); 278 279 final String location = "generated:" + getServiceType(); 280 281 if (connectionManager instanceof JamesConnectionManager) { 282 String connectionLimitString = conf.getChild("connectionLimit").getValue(null); 283 if (connectionLimitString != null) { 284 try { 285 connectionLimit = new Integer (connectionLimitString); 286 } catch (NumberFormatException nfe) { 287 getLogger().error("Connection limit value is not properly formatted.", nfe); 288 } 289 if (connectionLimit.intValue() < 0) { 290 getLogger().error("Connection limit value cannot be less than zero."); 291 throw new ConfigurationException("Connection limit value cannot be less than zero."); 292 } 293 } else { 294 connectionLimit = new Integer (((JamesConnectionManager)connectionManager).getMaximumNumberOfOpenConnections()); 295 } 296 infoBuffer = new StringBuffer (128) 297 .append(getServiceType()) 298 .append(" will allow a maximum of ") 299 .append(connectionLimit.intValue()) 300 .append(" connections."); 301 getLogger().info(infoBuffer.toString()); 302 } 303 } 304 305 308 public void initialize() throws Exception { 309 if (!isEnabled()) { 310 getLogger().info(getServiceType() + " Disabled"); 311 System.out.println(getServiceType() + " Disabled"); 312 return; 313 } 314 getLogger().debug(getServiceType() + " init..."); 315 316 SocketManager socketManager = (SocketManager) compMgr.lookup(SocketManager.ROLE); 317 318 ThreadManager threadManager = (ThreadManager) compMgr.lookup(ThreadManager.ROLE); 319 320 if (threadGroup != null) { 321 threadPool = threadManager.getThreadPool(threadGroup); 322 } else { 323 threadPool = threadManager.getDefaultThreadPool(); 324 } 325 326 ServerSocketFactory factory = socketManager.getServerSocketFactory(serverSocketType); 327 ServerSocket serverSocket = factory.createServerSocket(port, backlog, bindTo); 328 329 if (null == connectionName) { 330 final StringBuffer sb = new StringBuffer (); 331 sb.append(serverSocketType); 332 sb.append(':'); 333 sb.append(port); 334 335 if (null != bindTo) { 336 sb.append('/'); 337 sb.append(bindTo); 338 } 339 connectionName = sb.toString(); 340 } 341 342 if ((connectionLimit != null) && 343 (connectionManager instanceof JamesConnectionManager)) { 344 if (null != threadPool) { 345 ((JamesConnectionManager)connectionManager).connect(connectionName, serverSocket, this, threadPool, connectionLimit.intValue()); 346 } 347 else { 348 ((JamesConnectionManager)connectionManager).connect(connectionName, serverSocket, this, connectionLimit.intValue()); } 350 } else { 351 if (null != threadPool) { 352 connectionManager.connect(connectionName, serverSocket, this, threadPool); 353 } 354 else { 355 connectionManager.connect(connectionName, serverSocket, this); } 357 } 358 359 getLogger().debug(getServiceType() + " ...init end"); 360 361 StringBuffer logBuffer = 362 new StringBuffer (64) 363 .append(getServiceType()) 364 .append(" started ") 365 .append(connectionName); 366 String logString = logBuffer.toString(); 367 System.out.println(logString); 368 getLogger().info(logString); 369 } 370 371 374 public void dispose() { 375 376 if (!isEnabled()) { 377 return; 378 } 379 StringBuffer infoBuffer = 380 new StringBuffer (64) 381 .append(getServiceType()) 382 .append(" dispose... ") 383 .append(connectionName); 384 getLogger().debug(infoBuffer.toString()); 385 386 try { 387 connectionManager.disconnect(connectionName, true); 388 } catch (final Exception e) { 389 StringBuffer warnBuffer = 390 new StringBuffer (64) 391 .append("Error disconnecting ") 392 .append(getServiceType()) 393 .append(": "); 394 getLogger().warn(warnBuffer.toString(), e); 395 } 396 397 compMgr = null; 398 399 connectionManager = null; 400 threadPool = null; 401 402 System.gc(); 405 406 getLogger().debug(getServiceType() + " ...dispose end"); 407 } 408 409 416 protected WatchdogFactory getWatchdogFactory() { 417 WatchdogFactory theWatchdogFactory = null; 418 theWatchdogFactory = new ThreadPerWatchdogFactory(threadPool, timeout); 419 if (theWatchdogFactory instanceof LogEnabled) { 420 ((LogEnabled)theWatchdogFactory).enableLogging(getLogger()); 421 } 422 return theWatchdogFactory; 423 } 424 425 426 431 public final boolean isEnabled() { 432 return enabled; 433 } 434 440 protected abstract ConnectionHandler newHandler() 441 throws Exception ; 442 443 452 protected int getDefaultPort() { 453 return 0; 454 } 455 456 461 protected boolean isDefaultTLSEnabled() { 462 return false; 463 } 464 465 475 public String getServiceType() { 476 String name = getClass().getName(); 477 int p = name.lastIndexOf("."); 478 if (p > 0 && p < name.length() - 2) { 479 name = name.substring(p + 1); 480 } 481 return name; 482 } 483 484 489 public int getPort() { 490 return port; 491 } 492 493 498 public String getNetworkInterface() { 499 if (bindTo == null) { 500 return "All"; 501 } else { 502 return bindTo.getHostAddress(); 503 } 504 } 505 506 511 public String getSocketType() { 512 return serverSocketType; 513 } 514 } 515 516 | Popular Tags |