Source Code Cross Referenced for WebServer.java in  » EJB-Server-JBoss-4.2.1 » server » org » jboss » web » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » EJB Server JBoss 4.2.1 » server » org.jboss.web 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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.io.BufferedInputStream;
025:        import java.io.BufferedReader;
026:        import java.io.ByteArrayOutputStream;
027:        import java.io.DataOutputStream;
028:        import java.io.IOException;
029:        import java.io.InputStream;
030:        import java.io.InputStreamReader;
031:        import java.net.InetAddress;
032:        import java.net.MalformedURLException;
033:        import java.net.ServerSocket;
034:        import java.net.Socket;
035:        import java.net.URL;
036:        import java.util.Properties;
037:
038:        import org.jboss.logging.Logger;
039:        import org.jboss.util.threadpool.BasicThreadPool;
040:        import org.jboss.util.threadpool.BasicThreadPoolMBean;
041:
042:        import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
043:
044:        /**
045:         * A mini webserver that should be embedded in another application. It can
046:         * server any file that is available from classloaders that are registered with
047:         * it, including class-files.
048:         *
049:         * Its primary purpose is to simplify dynamic class-loading in RMI. Create an
050:         * instance of it, register a classloader with your classes, start it, and
051:         * you'll be able to let RMI-clients dynamically download classes from it.
052:         *
053:         * It is configured by calling any methods programmatically prior to startup.
054:         * @author <a href="mailto:marc@jboss.org">Marc Fleury</a>
055:         * @author <a href="mailto:Scott.Stark@org.jboss">Scott Stark</a>
056:         * @authro <a href="mailto:dimitris@jboss.org">Dimitris Andreadis</a>
057:         * @version $Revision: 62433 $
058:         * @see WebClassLoader
059:         */
060:        public class WebServer implements  Runnable {
061:            // Constants -----------------------------------------------------
062:
063:            // Attributes ----------------------------------------------------
064:            private static Logger log = Logger.getLogger(WebServer.class);
065:
066:            /**
067:             * The port the web server listens on
068:             */
069:            private int port = 8083;
070:
071:            /**
072:             * The interface to bind to. This is useful for multi-homed hosts that want
073:             * control over which interfaces accept connections.
074:             */
075:            private InetAddress bindAddress;
076:
077:            /**
078:             * The serverSocket listen queue depth
079:             */
080:            private int backlog = 50;
081:
082:            /**
083:             * The map of class loaders registered with the web server
084:             */
085:            private final ConcurrentReaderHashMap loaderMap = new ConcurrentReaderHashMap();
086:
087:            /**
088:             * The web server http listening socket
089:             */
090:            private ServerSocket server = null;
091:
092:            /**
093:             * A flag indicating if the server should attempt to download classes from
094:             * thread context class loader when a request arrives that does not have a
095:             * class loader key prefix.
096:             */
097:            private boolean downloadServerClasses = true;
098:
099:            /**
100:             * A flag indicating if the server should attempt to download resources,
101:             * i.e. resource paths that don't end in .class
102:             */
103:            private boolean downloadResources = false;
104:
105:            /**
106:             * The class wide mapping of type suffixes(class, txt) to their mime type
107:             * string used as the Content-Type header for the vended classes/resources
108:             */
109:            private static final Properties mimeTypes = new Properties();
110:
111:            /**
112:             * The thread pool used to manage listening threads
113:             */
114:            private BasicThreadPoolMBean threadPool;
115:
116:            // Public --------------------------------------------------------
117:
118:            /**
119:             * Set the http listening port
120:             */
121:            public void setPort(int port) {
122:                this .port = port;
123:            }
124:
125:            /**
126:             * Get the http listening port
127:             * @return the http listening port
128:             */
129:            public int getPort() {
130:                return port;
131:            }
132:
133:            /**
134:             * Set the http server bind address
135:             * @param bindAddress
136:             */
137:            public void setBindAddress(InetAddress bindAddress) {
138:                this .bindAddress = bindAddress;
139:
140:            }
141:
142:            /**
143:             * Get the address the http server binds to
144:             * @return the http bind address
145:             */
146:            public InetAddress getBindAddress() {
147:                return bindAddress;
148:            }
149:
150:            /**
151:             * Get the server sockets listen queue depth
152:             * @return the listen queue depth
153:             */
154:            public int getBacklog() {
155:                return backlog;
156:            }
157:
158:            /**
159:             * Set the server sockets listen queue depth
160:             */
161:            public void setBacklog(int backlog) {
162:                if (backlog <= 0)
163:                    backlog = 50;
164:
165:                this .backlog = backlog;
166:            }
167:
168:            public boolean getDownloadServerClasses() {
169:                return downloadServerClasses;
170:            }
171:
172:            public void setDownloadServerClasses(boolean flag) {
173:                downloadServerClasses = flag;
174:            }
175:
176:            public boolean getDownloadResources() {
177:                return downloadResources;
178:            }
179:
180:            public void setDownloadResources(boolean flag) {
181:                downloadResources = flag;
182:            }
183:
184:            public BasicThreadPoolMBean getThreadPool() {
185:                return threadPool;
186:            }
187:
188:            public void setThreadPool(BasicThreadPoolMBean threadPool) {
189:                this .threadPool = threadPool;
190:            }
191:
192:            /**
193:             * Augment the type suffix to mime type mappings
194:             * @param extension - the type extension without a period(class, txt)
195:             * @param type - the mime type string
196:             */
197:            public void addMimeType(String extension, String type) {
198:                mimeTypes.put(extension, type);
199:            }
200:
201:            /**
202:             * Start the web server on port and begin listening for requests.
203:             */
204:            public void start() throws Exception {
205:                if (threadPool == null)
206:                    threadPool = new BasicThreadPool("ClassLoadingPool");
207:
208:                try {
209:                    server = new ServerSocket(port, backlog, bindAddress);
210:                    log.debug("Started server: " + server);
211:
212:                    listen();
213:                } catch (java.net.BindException be) {
214:                    throw new Exception("Port " + port + " already in use.", be);
215:                } catch (IOException e) {
216:                    throw e;
217:                }
218:            }
219:
220:            /**
221:             * Close the web server listening socket
222:             */
223:            public void stop() {
224:                try {
225:                    ServerSocket srv = server;
226:                    server = null;
227:                    srv.close();
228:                } catch (Exception ignore) {
229:                }
230:            }
231:
232:            /**
233:             * Add a class loader to the web server map and return the URL that should be
234:             * used as the annotated codebase for classes that are to be available via
235:             * RMI dynamic classloading. The codebase URL is formed by taking the
236:             * java.rmi.server.codebase system property and adding a subpath unique for
237:             * the class loader instance.
238:             * @param cl - the ClassLoader instance to begin serving download requests
239:             * for
240:             * @return the annotated codebase to use if java.rmi.server.codebase is set,
241:             *         null otherwise.
242:             * @see #getClassLoaderKey(ClassLoader)
243:             */
244:            public URL addClassLoader(ClassLoader cl) {
245:                String key = (cl instanceof  WebClassLoader) ? ((WebClassLoader) cl)
246:                        .getKey()
247:                        : getClassLoaderKey(cl);
248:                loaderMap.put(key, cl);
249:                URL loaderURL = null;
250:                String codebase = System
251:                        .getProperty("java.rmi.server.codebase");
252:                if (codebase != null) {
253:                    if (codebase.endsWith("/") == false)
254:                        codebase += '/';
255:                    codebase += key;
256:                    codebase += '/';
257:                    try {
258:                        loaderURL = new URL(codebase);
259:                    } catch (MalformedURLException e) {
260:                        log.error("invalid url", e);
261:                    }
262:                }
263:                log.trace("Added ClassLoader: " + cl + " URL: " + loaderURL);
264:                return loaderURL;
265:            }
266:
267:            /**
268:             * Remove a class loader previously added via addClassLoader
269:             * @param cl - the ClassLoader previously added via addClassLoader
270:             */
271:            public void removeClassLoader(ClassLoader cl) {
272:                String key = getClassLoaderKey(cl);
273:                loaderMap.remove(key);
274:            }
275:
276:            // Runnable implementation ---------------------------------------
277:            /**
278:             * Listen threads entry point. Here we accept a client connection and located
279:             * requested classes/resources using the class loader specified in the http
280:             * request.
281:             */
282:            public void run() {
283:                // Return if the server has been stopped
284:                if (server == null)
285:                    return;
286:
287:                // Accept a connection
288:                Socket socket = null;
289:                try {
290:                    socket = server.accept();
291:                } catch (IOException e) {
292:                    // If the server is not null meaning we were not stopped report the err
293:                    if (server != null)
294:                        log.error("Failed to accept connection", e);
295:                    return;
296:                }
297:
298:                // Create a new thread to accept the next connection
299:                listen();
300:
301:                try {
302:                    // Get the request socket output stream
303:                    DataOutputStream out = new DataOutputStream(socket
304:                            .getOutputStream());
305:                    try {
306:                        String httpCode = "200 OK";
307:                        // Get the requested item from the HTTP header
308:                        BufferedReader in = new BufferedReader(
309:                                new InputStreamReader(socket.getInputStream()));
310:                        String rawPath = getPath(in);
311:
312:                        // Parse the path into the class loader key and file path.
313:                        //
314:                        // The class loader key is a string whose format is
315:                        // "ClassName[oid]",  where the oid substring may contain '/'
316:                        // chars. The expected form of the raw path is:
317:                        //
318:                        //     "SomeClassName[some/object/id]/some/file/path"
319:                        //
320:                        // The class loader key is "SomeClassName[some/object/id]"
321:                        // and the file path is "some/file/path"
322:
323:                        int endOfKey = rawPath.indexOf(']');
324:                        String filePath = rawPath.substring(endOfKey + 2);
325:                        String loaderKey = rawPath.substring(0, endOfKey + 1);
326:                        log.trace("loaderKey = " + loaderKey);
327:                        log.trace("filePath = " + filePath);
328:                        ClassLoader loader = (ClassLoader) loaderMap
329:                                .get(loaderKey);
330:                        /* If we did not find a class loader check to see if the raw path
331:                           begins with className + '[' + class loader key + ']' by looking for
332:                           an '[' char. If it does not and downloadServerClasses is true use
333:                           the thread context class loader and set filePath to the rawPath
334:                         */
335:                        if (loader == null && rawPath.indexOf('[') < 0
336:                                && downloadServerClasses) {
337:                            filePath = rawPath;
338:                            log
339:                                    .trace("No loader, reset filePath = "
340:                                            + filePath);
341:                            loader = Thread.currentThread()
342:                                    .getContextClassLoader();
343:                        }
344:                        log.trace("loader = " + loader);
345:                        byte[] bytes = {};
346:                        if (loader != null && filePath.endsWith(".class")) {
347:                            // A request for a class file
348:                            String className = filePath.substring(0,
349:                                    filePath.length() - 6).replace('/', '.');
350:                            log.trace("loading className = " + className);
351:                            Class clazz = loader.loadClass(className);
352:                            URL clazzUrl = clazz.getProtectionDomain()
353:                                    .getCodeSource().getLocation();
354:                            log.trace("clazzUrl = " + clazzUrl);
355:                            if (clazzUrl == null) {
356:                                // Does the WebClassLoader of clazz
357:                                // have the ability to obtain the bytecodes of clazz?
358:                                bytes = ((WebClassLoader) clazz
359:                                        .getClassLoader()).getBytes(clazz);
360:                                if (bytes == null)
361:                                    throw new Exception("Class not found: "
362:                                            + className);
363:                            } else {
364:                                if (clazzUrl.getFile().endsWith("/") == false) {
365:                                    clazzUrl = new URL("jar:" + clazzUrl + "!/"
366:                                            + filePath);
367:                                }
368:                                // this is a hack for the AOP ClassProxyFactory
369:                                else if (clazzUrl.getFile().indexOf(
370:                                        "/org_jboss_aop_proxy$") < 0) {
371:                                    clazzUrl = new URL(clazzUrl, filePath);
372:                                }
373:
374:                                // Retrieve bytecodes
375:                                log.trace("new clazzUrl: " + clazzUrl);
376:                                bytes = getBytes(clazzUrl);
377:                            }
378:                        } else if (loader != null && filePath.length() > 0
379:                                && downloadServerClasses && downloadResources) {
380:                            // Try getting resource
381:                            log.trace("loading resource = " + filePath);
382:                            URL resourceURL = loader.getResource(filePath);
383:                            if (resourceURL == null)
384:                                httpCode = "404 Resource not found:" + filePath;
385:                            else {
386:                                // Retrieve bytes
387:                                log.trace("resourceURL = " + resourceURL);
388:                                bytes = getBytes(resourceURL);
389:                            }
390:                        } else {
391:                            httpCode = "404 Not Found";
392:                        }
393:
394:                        // Send bytecodes/resource data in response (assumes HTTP/1.0 or later)
395:                        try {
396:                            log.trace("HTTP code=" + httpCode
397:                                    + ", Content-Length: " + bytes.length);
398:                            // The HTTP 1.0 header
399:                            out.writeBytes("HTTP/1.0 " + httpCode + "\r\n");
400:                            out.writeBytes("Content-Length: " + bytes.length
401:                                    + "\r\n");
402:                            out.writeBytes("Content-Type: "
403:                                    + getMimeType(filePath));
404:                            out.writeBytes("\r\n\r\n");
405:                            // The response body
406:                            out.write(bytes);
407:                            out.flush();
408:                        } catch (IOException ie) {
409:                            return;
410:                        }
411:                    } catch (Throwable e) {
412:                        try {
413:                            log.trace("HTTP code=404 " + e.getMessage());
414:                            // Write out error response
415:                            out.writeBytes("HTTP/1.0 400 " + e.getMessage()
416:                                    + "\r\n");
417:                            out.writeBytes("Content-Type: text/html\r\n\r\n");
418:                            out.flush();
419:                        } catch (IOException ex) {
420:                            // Ignore
421:                        }
422:                    }
423:                } catch (IOException ex) {
424:                    log.error("error writting response", ex);
425:                } finally {
426:                    // Close the client request socket
427:                    try {
428:                        socket.close();
429:                    } catch (IOException e) {
430:                    }
431:                }
432:            }
433:
434:            // Protected -----------------------------------------------------
435:            /**
436:             * Create the string key used as the key into the loaderMap.
437:             * @return The class loader instance key.
438:             */
439:            protected String getClassLoaderKey(ClassLoader cl) {
440:                String className = cl.getClass().getName();
441:                int dot = className.lastIndexOf('.');
442:                if (dot >= 0)
443:                    className = className.substring(dot + 1);
444:                String key = className + '[' + cl.hashCode() + ']';
445:                return key;
446:            }
447:
448:            protected void listen() {
449:                threadPool.getInstance().run(this );
450:            }
451:
452:            /**
453:             * @return the path portion of the HTTP request header.
454:             */
455:            protected String getPath(BufferedReader in) throws IOException {
456:                String line = in.readLine();
457:                log.trace("raw request=" + line);
458:                // Find the request path by parsing the 'REQUEST_TYPE filePath HTTP_VERSION' string
459:                int start = line.indexOf(' ') + 1;
460:                int end = line.indexOf(' ', start + 1);
461:                // The file minus the leading '/'
462:                String filePath = line.substring(start + 1, end);
463:                return filePath;
464:            }
465:
466:            /**
467:             * Read the local class/resource contents into a byte array.
468:             */
469:            protected byte[] getBytes(URL url) throws IOException {
470:                InputStream in = new BufferedInputStream(url.openStream());
471:                log.debug("Retrieving " + url);
472:                ByteArrayOutputStream out = new ByteArrayOutputStream();
473:                byte[] tmp = new byte[1024];
474:                int bytes;
475:                while ((bytes = in.read(tmp)) != -1) {
476:                    out.write(tmp, 0, bytes);
477:                }
478:                in.close();
479:                return out.toByteArray();
480:            }
481:
482:            /**
483:             * Lookup the mime type for the suffix of the path argument.
484:             * @return the mime-type string for path.
485:             */
486:            protected String getMimeType(String path) {
487:                int dot = path.lastIndexOf(".");
488:                String type = "text/html";
489:                if (dot >= 0) {
490:                    // The suffix is the type extension without the '.'
491:                    String suffix = path.substring(dot + 1);
492:                    String mimeType = mimeTypes.getProperty(suffix);
493:                    if (mimeType != null)
494:                        type = mimeType;
495:                }
496:                return type;
497:            }
498:
499:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.