001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.web;
023:
024: import java.net.InetAddress;
025: import java.net.URL;
026: import java.net.UnknownHostException;
027: import java.util.Enumeration;
028: import java.util.Properties;
029:
030: import javax.management.MBeanServer;
031: import javax.management.ObjectName;
032:
033: import org.jboss.system.ServiceMBeanSupport;
034: import org.jboss.system.server.ServerConfig;
035: import org.jboss.system.server.ServerConfigUtil;
036: import org.jboss.util.threadpool.BasicThreadPoolMBean;
037:
038: /**
039: * The WebService implementation. It configures a WebServer instance to
040: * perform dynamic class and resource loading.
041: *
042: * @jmx:mbean
043: * extends="org.jboss.system.ServiceMBean"
044: * name="jboss:service=WebService"
045: *
046: * @version <tt>$Revision: 62433 $</tt>
047: * @author <a href="mailto:rickard.oberg@telkel.com">Rickard Oberg</a>
048: * @author <a href="mailto:Scott.Stark@jboss.org">Scott Stark</a>
049: * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
050: * @author <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
051: */
052: public class WebService extends ServiceMBeanSupport implements
053: WebServiceMBean {
054: //
055: // jason: WebService and WebServer classes should be merged into one
056: // WebService only provides a thin layer of JMX which WebServer
057: // can do just as well.
058: //
059: // Doing so will dramatically simplify this component.
060: //
061: // Rename to HTTPClassLoaderService to be clear that this is not
062: // a fully functional web server.
063: //
064:
065: /**
066: * The web server instance which does the work.
067: * <p>
068: * Note: This value shadows the MBeanServer server value
069: * from ServiceMBeanSupport.
070: */
071: private WebServer server = new WebServer();
072:
073: /** The host portion of the RMI codebase URL */
074: private String host;
075:
076: /**
077: * @jmx:managed-constructor
078: */
079: public WebService() {
080: super ();
081: }
082:
083: /**
084: * @jmx:managed-operation
085: */
086: public URL addClassLoader(ClassLoader cl) {
087: return server.addClassLoader(cl);
088: }
089:
090: /**
091: * @jmx:managed-operation
092: */
093: public void removeClassLoader(ClassLoader cl) {
094: server.removeClassLoader(cl);
095: }
096:
097: /**
098: * Set the WebService listening port.
099: *
100: * @jmx:managed-attribute
101: *
102: * @param port The listening port; 0 for anonymous
103: */
104: public void setPort(int port) {
105: server.setPort(port);
106: }
107:
108: /**
109: * Get the WebService listening port.
110: *
111: * @jmx:managed-attribute
112: */
113: public int getPort() {
114: return server.getPort();
115: }
116:
117: /**
118: * Set the name of the interface to use for the host portion of the
119: * RMI codebase URL.
120: *
121: * @jmx:managed-attribute
122: */
123: public void setHost(final String hostname) {
124: this .host = ServerConfigUtil.fixRemoteAddress(hostname);
125: }
126:
127: /**
128: * Get the name of the interface to use for the host portion of the
129: * RMI codebase URL.
130: *
131: * @jmx:managed-attribute
132: */
133: public String getHost() {
134: return host;
135: }
136:
137: /**
138: * Set the specific address the WebService listens on. This can be used on
139: * a multi-homed host for a ServerSocket that will only accept connect requests
140: * to one of its addresses.
141: *
142: * @jmx:managed-attribute
143: *
144: * @param address the interface name or IP address to bind. If host is null,
145: * connections on any/all local addresses will be allowed.
146: */
147: public void setBindAddress(String address)
148: throws UnknownHostException {
149: InetAddress bindAddress = toInetAddress(address);
150: server.setBindAddress(bindAddress);
151: }
152:
153: /**
154: * Get the specific address the WebService listens on.
155: *
156: * @jmx:managed-attribute
157: *
158: * @return the interface name or IP address the WebService binds to.
159: */
160: public String getBindAddress() {
161: InetAddress bindAddress = server.getBindAddress();
162:
163: if (bindAddress != null)
164: return bindAddress.getHostAddress();
165: else
166: return null;
167: }
168:
169: /**
170: * Get the WebService listen queue backlog limit. The maximum queue length
171: * for incoming connection indications (a request to connect) is set to the
172: * backlog parameter. If a connection indication arrives when the queue is
173: * full, the connection is refused.
174: *
175: * @jmx:managed-attribute
176: *
177: * @return the queue backlog limit.
178: */
179: public int getBacklog() {
180: return server.getBacklog();
181: }
182:
183: /**
184: * Set the WebService listen queue backlog limit. The maximum queue length
185: * for incoming connection indications (a request to connect) is set to the
186: * backlog parameter. If a connection indication arrives when the queue is
187: * full, the connection is refused.
188: *
189: * @jmx:managed-attribute
190: *
191: * @param backlog, the queue backlog limit.
192: */
193: public void setBacklog(int backlog) {
194: server.setBacklog(backlog);
195: }
196:
197: /** Set the thread pool used for the WebServer class loading.
198: * @jmx:managed-attribute
199: *
200: */
201: public void setThreadPool(BasicThreadPoolMBean threadPool) {
202: server.setThreadPool(threadPool);
203: }
204:
205: /**
206: * A flag indicating if the server should attempt to download classes from
207: * thread context class loader when a request arrives that does not have a
208: * class loader key prefix.
209: *
210: * @jmx:managed-attribute
211: */
212: public boolean getDownloadServerClasses() {
213: return server.getDownloadServerClasses();
214: }
215:
216: /**
217: * @jmx:managed-attribute
218: */
219: public void setDownloadServerClasses(boolean flag) {
220: server.setDownloadServerClasses(flag);
221: }
222:
223: /**
224: * A flag indicating if the server should attempt to download resources,
225: * i.e. resource paths that don't end in .class
226: *
227: * @jmx:managed-attribute
228: */
229: public boolean getDownloadResources() {
230: return server.getDownloadResources();
231: }
232:
233: /**
234: * @jmx:managed-attribute
235: */
236: public void setDownloadResources(boolean flag) {
237: server.setDownloadResources(flag);
238: }
239:
240: /**
241: * The RMI codebase URL.
242: *
243: * @jmx:managed-attribute
244: */
245: public String getCodebase() {
246: return System.getProperty("java.rmi.server.codebase");
247: }
248:
249: protected ObjectName getObjectName(MBeanServer server,
250: ObjectName name)
251: throws javax.management.MalformedObjectNameException {
252: return name == null ? OBJECT_NAME : name;
253: }
254:
255: protected void createService() throws Exception {
256: // Load the file mime.types into the mapping list
257: Properties mimeTypes = new Properties();
258:
259: try {
260: mimeTypes.load(Thread.currentThread()
261: .getContextClassLoader().getResourceAsStream(
262: "org/jboss/web/mime.types"));
263:
264: Enumeration keys = mimeTypes.keys();
265: while (keys.hasMoreElements()) {
266: String extension = (String) keys.nextElement();
267: String type = mimeTypes.getProperty(extension);
268: server.addMimeType(extension, type);
269: }
270: } catch (Exception e) {
271: log
272: .error(
273: "Failed to load org/jboss/web/mime.types; ignoring",
274: e);
275: }
276:
277: // if no override has been specified, default to the jboss bind address
278: if (getBindAddress() == null)
279: setBindAddress(System
280: .getProperty(ServerConfig.SERVER_BIND_ADDRESS));
281:
282: // if no host specified, default to the java.rmi.server.hostname property value
283: if (getHost() == null)
284: setHost(System.getProperty("java.rmi.server.hostname"));
285:
286: // Set the rmi codebase if it is not already set
287: String codebase = getCodebase();
288: if (codebase == null)
289: ;
290: {
291: codebase = "http://" + getHost() + ":" + getPort() + "/";
292: System.setProperty("java.rmi.server.codebase", codebase);
293: }
294: log.info("Using RMI server codebase: " + codebase);
295: }
296:
297: /**
298: * Start the web server for dynamic downloading of classes and resources.
299: *
300: * <p>
301: * The system <tt>java.rmi.server.codebase</tt> is also set to
302: * <em>http://<host>:<port>/</em> if the property has not been set.
303: */
304: protected void startService() throws Exception {
305: // Start the WebServer running
306: server.start();
307: log.debug("Started WebServer with address: "
308: + server.getBindAddress() + ":" + getPort());
309: }
310:
311: protected void stopService() throws Exception {
312: server.stop();
313: log.debug("Stopped WebServer with address: "
314: + server.getBindAddress() + ":" + getPort());
315: }
316:
317: /**
318: * Safely convert a host string to InetAddress or null
319: */
320: private InetAddress toInetAddress(String host)
321: throws UnknownHostException {
322: if (host == null || host.length() == 0)
323: return null;
324: else
325: return InetAddress.getByName(host);
326: }
327: }
|