Source Code Cross Referenced for httpd.java in  » Web-Server » Jigsaw » org » w3c » jigsaw » http » 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 » Web Server » Jigsaw » org.w3c.jigsaw.http 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        // httpd.java
0002:        // $Id: httpd.java,v 1.142 2007/04/10 13:21:01 ylafon Exp $
0003:        // (c) COPYRIGHT MIT and INRIA, 1996.
0004:        // Please first read the full copyright statement in file COPYRIGHT.html
0005:
0006:        package org.w3c.jigsaw.http;
0007:
0008:        import java.io.ByteArrayInputStream;
0009:        import java.io.ByteArrayOutputStream;
0010:        import java.io.File;
0011:        import java.io.FileInputStream;
0012:        import java.io.FileNotFoundException;
0013:        import java.io.IOException;
0014:        import java.io.InputStream;
0015:        import java.io.PrintStream;
0016:
0017:        import java.util.Date;
0018:        import java.util.Enumeration;
0019:        import java.util.Hashtable;
0020:        import java.util.Properties;
0021:        import java.util.Vector;
0022:
0023:        import java.net.InetAddress;
0024:        import java.net.MalformedURLException;
0025:        import java.net.ServerSocket;
0026:        import java.net.Socket;
0027:        import java.net.URL;
0028:        import java.net.UnknownHostException;
0029:
0030:        import org.w3c.tools.resources.AbstractContainer;
0031:        import org.w3c.tools.resources.DummyResourceReference;
0032:        import org.w3c.tools.resources.FilterInterface;
0033:        import org.w3c.tools.resources.FramedResource;
0034:        import org.w3c.tools.resources.InvalidResourceException;
0035:        import org.w3c.tools.resources.LookupResult;
0036:        import org.w3c.tools.resources.LookupState;
0037:        import org.w3c.tools.resources.ProtocolException;
0038:        import org.w3c.tools.resources.ReplyInterface;
0039:        import org.w3c.tools.resources.RequestInterface;
0040:        import org.w3c.tools.resources.Resource;
0041:        import org.w3c.tools.resources.ResourceContext;
0042:        import org.w3c.tools.resources.ResourceException;
0043:        import org.w3c.tools.resources.ResourceFilter;
0044:        import org.w3c.tools.resources.ResourceReference;
0045:        import org.w3c.tools.resources.ResourceSpace;
0046:        import org.w3c.tools.resources.ServerInterface;
0047:
0048:        import org.w3c.tools.resources.store.ResourceStoreManager;
0049:
0050:        import org.w3c.tools.resources.indexer.IndexerModule;
0051:        import org.w3c.tools.resources.indexer.IndexersCatalog;
0052:        import org.w3c.tools.resources.indexer.ResourceIndexer;
0053:
0054:        import org.w3c.tools.timers.EventManager;
0055:
0056:        import org.w3c.jigsaw.auth.RealmsCatalog;
0057:
0058:        import org.w3c.jigsaw.resources.CheckpointResource;
0059:
0060:        import org.w3c.jigsaw.daemon.ServerHandler;
0061:        import org.w3c.jigsaw.daemon.ServerHandlerInitException;
0062:        import org.w3c.jigsaw.daemon.ServerHandlerManager;
0063:
0064:        import org.w3c.www.http.HTTP;
0065:        import org.w3c.www.http.HeaderValue;
0066:        import org.w3c.www.http.HttpEntityMessage;
0067:        import org.w3c.www.http.HttpFactory;
0068:        import org.w3c.www.http.HttpMessage;
0069:        import org.w3c.www.http.HttpReplyMessage;
0070:        import org.w3c.www.http.HttpRequestMessage;
0071:        import org.w3c.www.http.HttpTokenList;
0072:
0073:        import org.w3c.jigsaw.config.PropertySet;
0074:
0075:        import org.w3c.util.IO;
0076:        import org.w3c.util.ObservableProperties;
0077:        import org.w3c.util.PropertyMonitoring;
0078:        import org.w3c.util.Status;
0079:
0080:        import org.w3c.tools.resources.ProtocolException;
0081:        import org.w3c.tools.resources.upgrade.Upgrader;
0082:
0083:        import org.w3c.www.mime.MimeParserFactory;
0084:        import org.w3c.www.mime.MimeType;
0085:
0086:        /**
0087:         * <p>The server main class. This class can be used either through its
0088:         * main method, to run a full httpd server, or simply by importing it
0089:         * into your app. This latter possibility allows you to export some of
0090:         * your application state through http.
0091:         *
0092:         * <p>The server itself uses this to report about memory consumption,
0093:         * running threads, etc.
0094:         */
0095:
0096:        public class httpd implements  ServerInterface, Runnable,
0097:                PropertyMonitoring, Cloneable, Status {
0098:            /**
0099:             * The current displayed version of Jigsaw.
0100:             */
0101:            public static final String version = "2.2.6";
0102:            /**
0103:             * The current internal version counter of Jigsaw.
0104:             * This counter is bumped anytime the configuration needs upgrade.
0105:             */
0106:            public static final int verscount = 4;
0107:
0108:            /**
0109:             * debug flag
0110:             */
0111:            public static final boolean debug = true;
0112:
0113:            public static final String VERSCOUNT_P = "org.w3c.jigsaw.version.counter";
0114:            /**
0115:             * Name of the server software property.
0116:             * The server software is the string that gets emited by Jigsaw 
0117:             * on each reply, to tell the client what server emited the reply.
0118:             * <p>This property defaults to <strong>Jigsaw/1.0a</strong>.
0119:             */
0120:            public static final String SERVER_SOFTWARE_P = "org.w3c.jigsaw.server";
0121:            /**
0122:             * If the Host property is not set (see below), you can select if you
0123:             * want to use FQDN (broken on some jdk implementation) or just the IP
0124:             * address as the default host name, it usually defaults to "false"
0125:             * means, use FQDN.
0126:             */
0127:            public static final String DEFHOSTIP_P = "org.w3c.jigsaw.defhostip";
0128:            /**
0129:             * Name of the server host property.
0130:             * The host property should be set to the name of the host running
0131:             * this server.
0132:             * <p>This property defaults to the local host name, although if you want
0133:             * directory listing to work propertly, you might need to provide the 
0134:             * full host name (including its domain).
0135:             */
0136:            public static final String HOST_P = "org.w3c.jigsaw.host";
0137:            /**
0138:             * Name of the property giving the server root directory.
0139:             * <p>The server root directory is used to deduce a bunch of defaults
0140:             * properties, when they don't have any specific values.
0141:             * <p>This property has no defaults.
0142:             */
0143:            public static final String ROOT_P = "org.w3c.jigsaw.root";
0144:            /**
0145:             * Name of the property giving the server's config directory.
0146:             */
0147:            public static final String CONFIG_P = "org.w3c.jigsaw.config";
0148:            /**
0149:             * Name of the property giving the server space directory.
0150:             * The server space directory should contain an index file, built
0151:             * with the indexer.
0152:             * <p>This property defaults to <org.w3c.jigsaw.root>/WWW.
0153:             */
0154:            public static final String SPACE_P = "org.w3c.jigsaw.space";
0155:            /**
0156:             * Name of the server port property.
0157:             * At initializatiojn time, the server will bind its accepting socket
0158:             * to the host its runs on, and to the provided port.
0159:             * <p>This property defaults to <code>8888</code>.
0160:             */
0161:            public static final String PORT_P = "org.w3c.jigsaw.port";
0162:            /**
0163:             * Name of the server's trace property.
0164:             * When set to true, the server will emit some traces indicating 
0165:             * its current state by using the logger <em>trace</em> methods.
0166:             * This property should be set to <string>true</strong> if you want
0167:             * clients to emit traces.
0168:             * <p>This property defaults to <strong>false</strong>.
0169:             */
0170:            public static final String TRACE_P = "org.w3c.jigsaw.trace";
0171:            /**
0172:             * Name of the server's keep alive flag.
0173:             * This property is used to determine wether this server should keep
0174:             * its connection alive. Keeping connection alive requires this flag
0175:             * to set to <strong>true</strong>, and clients to be compliant to the
0176:             * keep alive feature as described in HTTP/1.1 specification.
0177:             * <p>This property defaults to <strong>true</strong>.
0178:             */
0179:            public static final String KEEP_ALIVE_P = "org.w3c.jigsaw.keepAlive";
0180:            /**
0181:             * Name of the server's connection time out property.
0182:             * This property gives, in milliseconds, the timeout to use for
0183:             * connections that remains idel, waiting for an incoming request.
0184:             * <p>This property defaults to <code>10000</code> milliseconds.
0185:             */
0186:            public static final String KEEP_TIMEOUT_P = "org.w3c.jigsaw.keep_alive.timeout";
0187:            /**
0188:             * Name of the server's request time out property.
0189:             * The request time out property value indicates, in milliseconds, the
0190:             * allowed duration of a request. Any request whose duration exceeds
0191:             * this time out value will be aborted.
0192:             * <p>This property defaults to <code>60000</code>.
0193:             */
0194:            public static final String REQUEST_TIMEOUT_P = "org.w3c.jigsaw.request.timeout";
0195:            /**
0196:             * Name of the client thread priority property.
0197:             * Every client threads will run at the given priority, which should be
0198:             * in the range of valid threads priority.
0199:             * <p>This property defaults to <code>Thread.NORM_PRIORITY</code>.
0200:             */
0201:            public static final String CLIENT_PRIORITY_P = "org.w3c.jigsaw.client.priority";
0202:            /**
0203:             * Nam eof the property giving the client output buffer size.
0204:             * Each clients, when not using a shuffler, has to allocate its own
0205:             * output buffer, Output buffer size may increase/decrease significantly
0206:             * the Jigsaw performances, so change it with care.
0207:             * <p>This property defaults to <code>8192</code>.
0208:             */
0209:            public static final String CLIENT_BUFSIZE_P = "org.w3c.jigsaw.client.bufsize";
0210:            /**
0211:             * Name of the property indicating wether client should be debuged.
0212:             * When debuged, clients emit some traces, through the server logger
0213:             * about their current state.
0214:             * <p>This property defaults to <strong>false</strong>.
0215:             */
0216:            public static final String CLIENT_DEBUG_P = "org.w3c.jigsaw.client.debug";
0217:            /**
0218:             * Name of  property that indicates if some security manager is required.
0219:             * You usually don't want to run a security manager for the server, 
0220:             * except in the unlikely (right now) case that you want the server to
0221:             * be able to host agents.
0222:             * <p>This property defaults to <string>false</strong>.
0223:             */
0224:            public static final String USE_SM_P = "org.w3c.http.useSecurityManager";
0225:            /**
0226:             * Name of property indicating the logger class to use.
0227:             * The Jigsaw server allows you to implement your own logger. The only
0228:             * logger provided with the core server is the 
0229:             * <code>org.w3c.jigsaw.core.CommonLogger</code>, which implements the
0230:             * common log format.
0231:             * <p>Property defaults to <code>org.w3c.jigsaw.core.CommonLogger</code>
0232:             */
0233:            public static final String LOGGER_P = "org.w3c.jigsaw.logger";
0234:            /**
0235:             * Name of property indicating the "lenient" mode of HTTP parsing.
0236:             * <p>Property defaults to <code>true</code>
0237:             */
0238:            public static final String LENIENT_P = "org.w3c.jigsaw.http.lenient";
0239:            /**
0240:             * Name of the property indicating the client factory class.
0241:             */
0242:            public static final String CLIENT_FACTORY_P = "org.w3c.jigsaw.http.ClientFactory";
0243:            /**
0244:             * Name of the property giving the shuffler path.
0245:             * This property should be set if you are to use the shuffler. The 
0246:             * data shuffler is an external process to whiuch Jigsaw delegates 
0247:             * the task of writing back document content to clients. Use this
0248:             * when you think your server isn't fast enough.
0249:             * <p>This should be an absloute path.
0250:             * <p>This property has no defaults.
0251:             */
0252:            public static final String SHUFFLER_PATH_P = "org.w3c.jigsaw.shuffler.path";
0253:
0254:            /**
0255:             * Name of the property giving the name of the root resource.
0256:             * Upon startup, or restart, the server will look in its root store
0257:             * a resource whose name is given by this resource, and install it as
0258:             * its root resource.
0259:             * <p>This property defaults to <code>root</code>.
0260:             */
0261:            public static final String ROOT_NAME_P = "org.w3c.jigsaw.root.name";
0262:            public static final String ROOT_CLASS_P = "org.w3c.jigsaw.root.class";
0263:
0264:            /**
0265:             * Max number of store loaded in memory.
0266:             */
0267:            public static final String MAX_LOADED_STORE_P = "org.w3c.jigsaw.loadedstore";
0268:            public static final int MAX_LOADED_STORE = 128;
0269:            int max_loaded_store = -1;
0270:
0271:            /**
0272:             * Max number of store loaded in memory.
0273:             */
0274:            public static final String STORE_SIZE_LIMIT_P = "org.w3c.jigsaw.storesize";
0275:            public static final int STORE_SIZE_LIMIT = -1;
0276:            int store_size_limit = -1;
0277:
0278:            /**
0279:             * Name of the property giving the path of the property file.
0280:             * this should be used internally (for restart) only.
0281:             * <p>This property defaults to <code>config/httpd.props</code>.
0282:             */
0283:            public static final String PROPS_P = "org.w3c.jigsaw.propfile";
0284:            /**
0285:             * Name of the property indicating if the file-system is case sensitive.
0286:             * This property determines wether Jigsaw will list all files to check 
0287:             * for case sensitivity, before creating a resource for that file.
0288:             * <p>For obvious security reasons, this property defaults to 
0289:             * <strong>true</strong>.
0290:             */
0291:            public static final String FS_SENSITIVITY = "org.w3c.jigsaw.checkSensitivity";
0292:            /**
0293:             * Name of the property indicating the URL of Jigsaw's help.
0294:             * This URL should point to the URL path of Jigsaw's documentation
0295:             * as served by that server.
0296:             */
0297:            public static String DOCURL_P = "org.w3c.jigsaw.docurl";
0298:
0299:            /**
0300:             * Name of the property indicating the startup classes to load
0301:             */
0302:            public static String STARTUP_P = "org.w3c.jigsaw.startup";
0303:
0304:            /**
0305:             * Name of the property indicating the trash directory.
0306:             */
0307:            public static String TRASHDIR_P = "org.w3c.jigsaw.trashdir";
0308:
0309:            /**
0310:             * Name of the property indicating the URL of Jigsaw's chekpointer.
0311:             */
0312:            public static String CHECKURL_P = "org.w3c.jigsaw.checkpointer";
0313:
0314:            /**
0315:             * Name of the property indicating the public methods allowed on that 
0316:             * server.
0317:             * This property should provide a <code>|</code> separated list of
0318:             * methods available on that server.
0319:             * <p>This property defaults to: <strong>GET | HEAD | PUT | POST 
0320:             * | OPTIONS | DELETE | LINK | UNLINK | TRACE</code>.
0321:             */
0322:            public static String PUBLIC_P = "org.w3c.jigsaw.publicMethods";
0323:            /**
0324:             * Name of the property that indicates the root resource for edit.
0325:             * The edit root resource is the one that will show up by default
0326:             * when accessing the admin server from JigAdmin.
0327:             */
0328:            public static String EDIT_ROOT_P = "org.w3c.jigsaw.edit.root";
0329:
0330:            /**
0331:             * Name of the serializer class used to store resources.
0332:             */
0333:            public static String SERIALIZER_CLASS_P = "org.w3c.jigsaw.serializer";
0334:
0335:            /**
0336:             * UNIX - Name of the property that indicates the server user.
0337:             * When set, the server will try to turn itself to the given user name
0338:             * after initialization. If this fail, the server will abort.
0339:             * <p>This property has no default value.
0340:             */
0341:            public static String SERVER_USER_P = "org.w3c.jigsaw.unix.user";
0342:            /**
0343:             * UNIX - Name of the property that indicates the server group.
0344:             * When set, the server will try to turn itself to the given group name
0345:             * after initialization. If this fail, the server will abort.
0346:             * <p>This property has no default value.
0347:             */
0348:            public static String SERVER_GROUP_P = "org.w3c.jigsaw.unix.group";
0349:
0350:            /**
0351:             * Should we show the URL that triggered an error in the error message
0352:             * or not?
0353:             * Displaying it can lead to so-called "cross-scripting" hacks
0354:             */
0355:            public static String DISPLAY_URL_ON_ERROR_P = "org.w3c.jigsaw.error.url";
0356:
0357:            /**
0358:             * The list of currently running servers.
0359:             */
0360:            private static Hashtable servers = new Hashtable();
0361:
0362:            /* FIXME */public Thread thread = null;
0363:
0364:            private String software = "Jigsaw/2.2.6";
0365:            private ServerSocket socket = null;
0366:            private Logger logger = null;
0367:            private Shuffler shuffler = null;
0368:            public EventManager timer = null;
0369:            ClientFactory factory = null;
0370:
0371:            // FIXME This is a temporary hack to take care of clones
0372:            protected int[] instances = { 1 }; // object containing the nb of clones
0373:
0374:            /**
0375:             * The (optional) server handler manager that created us.
0376:             */
0377:            private ServerHandlerManager shm = null;
0378:            /**
0379:             * The server identifier can be any String.
0380:             * This identifier is used by the configuration applets, to show all the 
0381:             * running servers in the process, and to edit their properties, etc.
0382:             */
0383:            private String identifier = null;
0384:
0385:            /**
0386:             * This server statistics object.
0387:             */
0388:            private httpdStatistics statistics = null;
0389:            /**
0390:             * This server set of properties.
0391:             */
0392:            protected ObservableProperties props = null;
0393:            /** 
0394:             * Should the server run the server in trace mode ?
0395:             */
0396:            private boolean tracep = false;
0397:            /**
0398:             * Should the server try to keep connections alive ?
0399:             */
0400:            private boolean keep = true;
0401:            /**
0402:             * What logger class should the server use to log accesses.
0403:             */
0404:            private String logger_class = null;
0405:            /**
0406:             * Should we display URL on error?
0407:             */
0408:            private boolean uri_error = false;
0409:            /**
0410:             * Are we lenient in HTTP mode?
0411:             */
0412:            private boolean lenient = true;
0413:            /**
0414:             * What client factory class should the server use.
0415:             */
0416:            private String factory_class = "org.w3c.jigsaw.http.socket.SocketClientFactory";
0417:            /**
0418:             * The coordinate of the shuffler, or <strong>null</strong> is none is to 
0419:             * be used. 
0420:             */
0421:            private String shuffler_path = null;
0422:            /**
0423:             * The server's root directory.
0424:             */
0425:            private File root_dir = null;
0426:            /**
0427:             * The directory containing the server exported documents.
0428:             */
0429:            private File space_dir = null;
0430:            /**
0431:             * FIXME check
0432:             * The server host name.
0433:             */
0434:            protected String host = null;
0435:            /**
0436:             * FIXME check
0437:             * The server port.
0438:             */
0439:            protected int port = 8001;
0440:            /**
0441:             * This server client debug flag.
0442:             */
0443:            private boolean client_debug = false;
0444:            /**
0445:             * This server's request time slice, in milliseconds.
0446:             */
0447:            private int request_time_out = 1200000;
0448:            /**
0449:             * This server's connection allowed idle time in milliseconds.
0450:             */
0451:            private int connection_time_out = 1200000;
0452:            /**
0453:             * This server's client thread priority.
0454:             */
0455:            private int client_priority = Thread.NORM_PRIORITY;
0456:            /**
0457:             * This server's clients buffer size.
0458:             */
0459:            private int client_bufsize = 4096;
0460:            /**
0461:             * Is the file system case-sensitive ?
0462:             */
0463:            private boolean sensitivity = true;
0464:            /**
0465:             * This server root entity.
0466:             */
0467:            public FramedResource root = null;
0468:            /**
0469:             * the old root ResourceReference
0470:             */
0471:            private ResourceReference root_reference = null;
0472:            /**
0473:             * FIXME check for clones
0474:             * This server URL.
0475:             */
0476:            protected URL url = null;
0477:            /**
0478:             * Finishing (killing) the server.
0479:             */
0480:            private boolean finishing = false;
0481:            /**
0482:             * Finishing, but restart straight up.
0483:             */
0484:            private boolean restarting = false;
0485:            /**
0486:             * The indexer attached to this server.
0487:             */
0488:            private ResourceIndexer indexer = null;
0489:            /**
0490:             * The realm catalog
0491:             */
0492:            private RealmsCatalog realms = null;
0493:            /**
0494:             * The resource store manager for this server.
0495:             */
0496:            private ResourceStoreManager manager = null;
0497:            /**
0498:             * The root resource's identifier.
0499:             */
0500:            private String root_name = null;
0501:            private String root_class = null;
0502:            /**
0503:             * The full URL of Jigsaw's documentation as served by that server.
0504:             */
0505:            private String docurl = null;
0506:
0507:            /**
0508:             * The trash directory
0509:             */
0510:            private String trashdir = null;
0511:
0512:            /**
0513:             * The full URL of Jigsaw's chekpointer.
0514:             */
0515:            private String checkurl = null;
0516:
0517:            /**
0518:             * The list of public methods for that server.
0519:             */
0520:            private String publicMethods[] = { "GET", "HEAD", "PUT", "POST",
0521:                    "LINK", "UNLINK", "DELETE", "OPTIONS", "TRACE" };
0522:            /**
0523:             * The <code>Public</code> header value, computed out of the
0524:             * <code>publicMethods</code> variable.
0525:             */
0526:            private HttpTokenList publicHeader = null;
0527:            /**
0528:             * The edit root for that server.
0529:             */
0530:            private ResourceReference editroot = null;
0531:            /**
0532:             * the sets of properties of this server
0533:             */
0534:            private Vector propSet = new Vector(8);
0535:            /**
0536:             * the catalog of indexers of this server 
0537:             */
0538:            private IndexersCatalog indexers = null;
0539:            /**
0540:             * the resource context of this server 
0541:             */
0542:            private ResourceContext context = null;
0543:            /**
0544:             * the config resource of this server
0545:             */
0546:            private AbstractContainer configResource = null;
0547:            /**
0548:             * and its dummy resource reference
0549:             */
0550:            private ResourceReference rr_configResource = null;
0551:
0552:            // is this server a clone?
0553:            private boolean isAClone = false;
0554:            // our master server ID, if we are a clone
0555:            private String masterID = null;
0556:
0557:            /**
0558:             * The property monitoring implementation.
0559:             * @param name The name of the property that has changed.
0560:             * @return A boolean, <strong>true</strong> if the changed was taken into
0561:             *    account, <strong>false</strong> otherwise.
0562:             */
0563:            public boolean propertyChanged(String name) {
0564:                // Is this a property we are interested in ?
0565:                if (name.equals(SERVER_SOFTWARE_P)) {
0566:                    software = props.getString(name, software);
0567:                    return true;
0568:                } else if (name.equals(TRACE_P)) {
0569:                    tracep = props.getBoolean(name, tracep);
0570:                    errlog(name + " changed to " + tracep);
0571:                    return true;
0572:                } else if (name.equals(LENIENT_P)) {
0573:                    lenient = props.getBoolean(name, lenient);
0574:                    errlog(name + " changed to " + lenient);
0575:                    return true;
0576:                } else if (name.equals(DISPLAY_URL_ON_ERROR_P)) {
0577:                    uri_error = props.getBoolean(name, uri_error);
0578:                    errlog(name + " changed to " + uri_error);
0579:                    return true;
0580:                } else if (name.equals(KEEP_ALIVE_P)) {
0581:                    keep = props.getBoolean(name, keep);
0582:                    errlog(name + " changed to " + keep);
0583:                    return true;
0584:                } else if (name.equals(LOGGER_P)) {
0585:                    String tmp_logger_class;
0586:                    Logger tmp_logger;
0587:                    tmp_logger_class = props.getString(name, logger_class);
0588:                    // for now the removal of the logger should be done by hand
0589:                    if (!tmp_logger_class.equals(logger_class)) {
0590:                        try {
0591:                            tmp_logger = (Logger) Class.forName(
0592:                                    tmp_logger_class).newInstance();
0593:                        } catch (Exception ex) {
0594:                            errlog(name + " change failed (bad logger class)");
0595:                            return false;
0596:                        }
0597:                        synchronized (this ) {
0598:                            if (logger != null) {
0599:                                logger.shutdown();
0600:                            }
0601:                            tmp_logger.initialize(this );
0602:                            logger = tmp_logger;
0603:                            logger_class = tmp_logger_class;
0604:                        }
0605:                    }
0606:                    return true;
0607:                } else if (name.equals(ROOT_NAME_P)) {
0608:                    String newname = props.getString(name, null);
0609:                    if (changeRoot(newname) != null) {
0610:                        errlog("new root resource [" + newname + "]");
0611:                        return true;
0612:                    } else {
0613:                        errlog("failed to change root to [" + newname + "].");
0614:                        return false;
0615:                    }
0616:                } else if (name.equals(SPACE_P)) {
0617:                    errlog(name + " change failed (server running)");
0618:                    return false;
0619:                } else if (name.equals(HOST_P)) {
0620:                    errlog(name + " change failed (server running)");
0621:                    return false;
0622:                } else if (name.equals(PORT_P)) {
0623:                    // we will restart the server
0624:                    errlog(name + " switching port : "
0625:                            + props.getInteger(name, 80));
0626:                    int newport = props.getInteger(name, 80);
0627:                    if (port != newport) {
0628:                        int oldport = port;
0629:                        port = newport;
0630:                        checkpoint();
0631:                        ServerSocket newsocket = null;
0632:                        try {
0633:                            newsocket = factory.createServerSocket();
0634:                            socket.close();
0635:                            socket = newsocket;
0636:                        } catch (Exception ex) {
0637:                            try {
0638:                                newsocket.close();
0639:                            } catch (Exception e) {
0640:                            }
0641:                            ;
0642:                            port = oldport;
0643:                            // an error occured, return false
0644:                            return false;
0645:                        }
0646:                    }
0647:                    return true;
0648:                } else if (name.equals(CLIENT_DEBUG_P)) {
0649:                    client_debug = props.getBoolean(name, client_debug);
0650:                    errlog(name + " changed to " + client_debug);
0651:                    return true;
0652:                } else if (name.equals(REQUEST_TIMEOUT_P)) {
0653:                    request_time_out = props.getInteger(name, request_time_out);
0654:                    errlog(name + " changed to " + request_time_out);
0655:                    return true;
0656:                } else if (name.equals(KEEP_TIMEOUT_P)) {
0657:                    connection_time_out = props.getInteger(name,
0658:                            connection_time_out);
0659:                    errlog(name + " changed to " + connection_time_out);
0660:                    return true;
0661:                } else if (name.equals(CLIENT_PRIORITY_P)) {
0662:                    client_priority = props.getInteger(name, client_priority);
0663:                    errlog(name + " changed to " + client_priority);
0664:                    return true;
0665:                } else if (name.equals(CLIENT_BUFSIZE_P)) {
0666:                    client_bufsize = props.getInteger(name, client_bufsize);
0667:                    errlog(name + " changed to " + client_bufsize);
0668:                    return true;
0669:                } else if (name.equals(DOCURL_P)) {
0670:                    String propval = props.getString(name, docurl);
0671:                    try {
0672:                        URL u = new URL(getURL(), propval);
0673:                        docurl = u.toExternalForm();
0674:                    } catch (Exception ex) {
0675:                        return false;
0676:                    }
0677:                    return true;
0678:                } else if (name.equals(TRASHDIR_P)) {
0679:                    trashdir = props.getString(name, trashdir);
0680:                    File dir = new File(trashdir);
0681:                    if (!dir.exists())
0682:                        dir.mkdirs();
0683:                    errlog(name + " changed to " + trashdir);
0684:                    return true;
0685:                } else if (name.equals(CHECKURL_P)) {
0686:                    checkurl = props.getString(name, checkurl);
0687:                    errlog(name + " changed to " + checkurl);
0688:                    return true;
0689:                } else if (name.equals(PUBLIC_P)) {
0690:                    publicMethods = props.getStringArray(name, publicMethods);
0691:                    publicHeader = null;
0692:                    return true;
0693:                } else if (name.equals(SERVER_USER_P)) {
0694:                    String user = props.getString(SERVER_USER_P, null);
0695:                    errlog("new user: " + user);
0696:                    return false;
0697:                } else if (name.equals(SERVER_GROUP_P)) {
0698:                    String group = props.getString(SERVER_GROUP_P, null);
0699:                    errlog("new group: " + group);
0700:                    return false;
0701:                } else {
0702:                    // We  don't care about this one
0703:                    return true;
0704:                }
0705:            }
0706:
0707:            /**
0708:             * Initialize this server indexer.
0709:             */
0710:            private void initializeIndexer() {
0711:                ResourceContext c = getDefaultContext();
0712:                IndexersCatalog ic = getIndexersCatalog();
0713:                IndexerModule m = new IndexerModule(ic);
0714:                // Register the default indexer:
0715:                m.registerIndexer(c, "default");
0716:                // Register the indexer module:
0717:                c.registerModule(IndexerModule.NAME, m);
0718:            }
0719:
0720:            /**
0721:             * Initialize the resource store manager for this server.
0722:             */
0723:            private void initializeResourceSpace(String server_name,
0724:                    String root_class, String root_name, String serializer,
0725:                    int max_loaded_store) {
0726:                Hashtable defs = new Hashtable(11);
0727:                defs.put("url", "/");
0728:                defs.put("directory", space_dir);
0729:                defs.put("context", getDefaultContext());
0730:                this .manager = new ResourceStoreManager(server_name, this 
0731:                        .getStoreDirectory(), root_class, root_name,
0732:                        serializer, max_loaded_store, store_size_limit, defs);
0733:            }
0734:
0735:            /**
0736:             * Lookup the root store for some resource.
0737:             * @param name The name of the resource to lookup in the root store.
0738:             * @return The loaded resource, or <strong>null</strong>.
0739:             */
0740:            public ResourceReference loadResource(String name) {
0741:                Hashtable defs = new Hashtable(11);
0742:                defs.put("url", "/" + name);
0743:                defs.put("directory", space_dir);
0744:                ResourceContext context = new ResourceContext(
0745:                        getDefaultContext());
0746:                defs.put("context", context);
0747:                ResourceReference rr = manager.loadRootResource(name, defs);
0748:                if (rr != null)
0749:                    context.setResourceReference(rr);
0750:                return rr;
0751:            }
0752:
0753:            /**
0754:             * start the automatic checkpoint
0755:             */
0756:            public void startCheckpoint() {
0757:                if (checkurl == null) {
0758:                    errlog("checkpointer URL unknown.");
0759:                    checkpoint();
0760:                    return;
0761:                }
0762:                try {
0763:                    LookupState ls = new LookupState(checkurl);
0764:                    LookupResult lr = new LookupResult(root
0765:                            .getResourceReference());
0766:                    if (root.lookup(ls, lr)) {
0767:                        ResourceReference target = lr.getTarget();
0768:                        if (target != null) {
0769:                            try {
0770:                                Resource res = target.lock();
0771:                                if (res instanceof  CheckpointResource) {
0772:                                    ((CheckpointResource) res).activate();
0773:                                    errlog("Chekpointer started at: "
0774:                                            + new Date() + ".");
0775:                                } else {
0776:                                    errlog("The chekpointer url ("
0777:                                            + checkurl
0778:                                            + ") doesn't point to a CheckpointResource");
0779:                                    checkpoint();
0780:                                }
0781:                            } catch (InvalidResourceException ex) {
0782:                                errlog("Invalid Checkpointer : "
0783:                                        + ex.getMessage());
0784:                                checkpoint();
0785:                            } finally {
0786:                                target.unlock();
0787:                            }
0788:                        } else {
0789:                            errlog("can't find Checkpointer");
0790:                            checkpoint();
0791:                        }
0792:                    } else {
0793:                        errlog("Checkpointer: lookup fail");
0794:                        checkpoint();
0795:                    }
0796:                } catch (ProtocolException ex) {
0797:                    errlog("Checkpointer : " + ex.getMessage());
0798:                    checkpoint();
0799:                }
0800:            }
0801:
0802:            /**
0803:             * Checkpoint all cached data, by saving them to disk.
0804:             */
0805:            public void checkpoint() {
0806:                manager.checkpoint();
0807:            }
0808:
0809:            /**
0810:             * Dynamically change the root resource for the server.
0811:             * This is kind a dangerous operation !
0812:             * @param name The name of the new root resource, to be found in the
0813:             * root resource store.
0814:             * @return The new installed root resource, or <strong>null</strong>
0815:             * if we couldn't load the given resource.
0816:             */
0817:            public synchronized ResourceReference loadRoot(String name) {
0818:                ResourceReference newroot = null;
0819:                String editRootName = props.getString(EDIT_ROOT_P, null);
0820:
0821:                // Restore the appropriate root resource:
0822:                Hashtable defs = new Hashtable(11);
0823:                defs.put("url", "/");
0824:                defs.put("directory", space_dir);
0825:                ResourceContext context = null;
0826:                if ((editRootName != null) && (!name.equals(editRootName))) {
0827:                    if (editroot == null) {
0828:                        Hashtable edefs = new Hashtable(11);
0829:                        edefs.put("url", "/");
0830:                        edefs.put("directory", space_dir);
0831:                        ResourceContext econtext = new ResourceContext(
0832:                                getDefaultContext());
0833:                        edefs.put("context", econtext);
0834:                        editroot = manager
0835:                                .loadRootResource(editRootName, edefs);
0836:                        if (editroot != null)
0837:                            econtext.setResourceReference(editroot);
0838:                    }
0839:                    context = new ResourceContext(editroot);
0840:                } else {
0841:                    context = new ResourceContext(getDefaultContext());
0842:                }
0843:                defs.put("context", context);
0844:                ResourceReference rr = manager.loadRootResource(name, defs);
0845:                if (rr != null)
0846:                    context.setResourceReference(rr);
0847:                return rr;
0848:            }
0849:
0850:            private synchronized FramedResource changeRoot(String name) {
0851:                ResourceReference newroot = loadRoot(name);
0852:                FramedResource oldroot = this .root;
0853:                String oldroot_name = this .root_name;
0854:                if (newroot != null) {
0855:                    try {
0856:                        this .root = (FramedResource) newroot.lock();
0857:                        this .root_name = name;
0858:                        if (root_reference != null)
0859:                            root_reference.unlock();
0860:                        root_reference = newroot;
0861:                        return root;
0862:                    } catch (InvalidResourceException ex) {
0863:                        this .root = oldroot;
0864:                        this .root_name = oldroot_name;
0865:                        return null;
0866:                    }
0867:                }
0868:                return null;
0869:            }
0870:
0871:            /**
0872:             * Initialize this server's root resource.
0873:             * @exception ServerHandlerInitException if unable to be initialized.
0874:             */
0875:
0876:            private void initializeRootResource()
0877:                    throws ServerHandlerInitException {
0878:                // Check for un-found root resource:
0879:                if (changeRoot(root_name) == null) {
0880:                    String err = ("Unable to restore root resource ["
0881:                            + root_name + "]" + " from store (not found).");
0882:                    throw new ServerHandlerInitException(err);
0883:                }
0884:            }
0885:
0886:            /**
0887:             * Initialize the realms catalog for this server.
0888:             */
0889:
0890:            private void initializeRealmsCatalog() {
0891:                this .realms = new RealmsCatalog(new ResourceContext(
0892:                        getDefaultContext()));
0893:            }
0894:
0895:            /**
0896:             * Initialize the server logger and the statistics object.
0897:             * @exception ServerHandlerInitException if unable to be initialized.
0898:             */
0899:
0900:            private void initializeLogger() throws ServerHandlerInitException {
0901:                if (logger_class != null) {
0902:                    try {
0903:                        logger = (Logger) Class.forName(logger_class)
0904:                                .newInstance();
0905:                        logger.initialize(this );
0906:                    } catch (Exception ex) {
0907:                        String err = ("Unable to create logger of class ["
0908:                                + logger_class + "]" + "\r\ndetails: \r\n" + ex
0909:                                .getMessage());
0910:                        throw new ServerHandlerInitException(err);
0911:                    }
0912:                } else {
0913:                    warning(getBanner() + ": no logger specified, not logging.");
0914:                }
0915:                // Initialize the statistics object:
0916:                statistics = new httpdStatistics(this );
0917:            }
0918:
0919:            /**
0920:             * Initialize the server socket, create a suitable client factory, start.
0921:             * This method creates the physicall listening socket, and instantiate
0922:             * an appropriate client factory for that socket. It then run the accept
0923:             * thread, ready to accept new incomming connections.
0924:             * @exception ServerHandlerInitException if unable to be initialized.
0925:             */
0926:
0927:            private void initializeServerSocket()
0928:                    throws ServerHandlerInitException {
0929:                // Create a suitable client factory:
0930:                try {
0931:                    Class c = Class.forName(factory_class);
0932:                    factory = (ClientFactory) c.newInstance();
0933:                    factory.initialize(this );
0934:                } catch (Exception ex) {
0935:                    String err = ("Unable to create a client factory of class "
0936:                            + "\"" + factory_class + "\"" + " details: \r\n" + ex
0937:                            .getMessage());
0938:                    throw new ServerHandlerInitException(err);
0939:                }
0940:                // If needed, create a server socket instance for that context:
0941:                try {
0942:                    socket = factory.createServerSocket();
0943:                } catch (IOException ex) {
0944:                    String err = ("Unable to create server socket on port "
0945:                            + port + ": " + ex.getMessage() + ".");
0946:                    throw new ServerHandlerInitException(err);
0947:                }
0948:                this .thread = new Thread(this );
0949:                this .thread.setName(identifier);
0950:                this .thread.setPriority(Thread.MAX_PRIORITY);
0951:            }
0952:
0953:            protected MimeParserFactory getMimeClientFactory(Client client) {
0954:                return new MimeClientFactory(client);
0955:            }
0956:
0957:            /**
0958:             * Initialize our event manager.
0959:             */
0960:
0961:            private void initializeEventManager() {
0962:                this .timer = new EventManager();
0963:                this .timer.setDaemon(true);
0964:                this .timer.start();
0965:            }
0966:
0967:            /**
0968:             * startup classes
0969:             */
0970:            protected void loadStartupClasses() {
0971:                String classes[] = props.getStringArray(STARTUP_P, null);
0972:                if (classes != null) {
0973:                    for (int i = 0; i < classes.length; i++) {
0974:                        try {
0975:                            Class c = Class.forName(classes[i]);
0976:                            httpdPreloadInterface hpi = (httpdPreloadInterface) c
0977:                                    .newInstance();
0978:                            hpi.preload(this );
0979:                        } catch (ClassNotFoundException cnfex) {
0980:                            errlog("Startup class not found : "
0981:                                    + cnfex.getMessage());
0982:                        } catch (InstantiationException iex) {
0983:                            errlog("Unable to instanciate : "
0984:                                    + iex.getMessage());
0985:                        } catch (ClassCastException ccex) {
0986:                            errlog("Startup classes must be instance of "
0987:                                    + "httpdPreloadInterface: "
0988:                                    + ccex.getMessage());
0989:                        } catch (IllegalAccessException iaex) {
0990:                            errlog("IllegalAccess " + iaex.getMessage());
0991:                        }
0992:                    }
0993:                }
0994:            }
0995:
0996:            /**
0997:             * FIXME protected for now to handle clones
0998:             * Initialize some of the servers instance values from properties.
0999:             * @exception ServerHandlerInitException if unable to be initialized.
1000:             */
1001:
1002:            protected void initializeProperties()
1003:                    throws ServerHandlerInitException {
1004:                // Compute some default values (host and port)
1005:                String defhost = null;
1006:                String rootstr = null;
1007:                String spacestr = null;
1008:
1009:                boolean ip_host = props.getBoolean(DEFHOSTIP_P, false);
1010:
1011:                try {
1012:                    if (ip_host)
1013:                        defhost = InetAddress.getLocalHost().getHostAddress();
1014:                    else
1015:                        defhost = InetAddress.getLocalHost().getHostName();
1016:                } catch (UnknownHostException e) {
1017:                    defhost = null;
1018:                }
1019:                // Second stage: get property values:
1020:                software = props.getString(SERVER_SOFTWARE_P, software);
1021:                tracep = props.getBoolean(TRACE_P, tracep);
1022:                uri_error = props.getBoolean(DISPLAY_URL_ON_ERROR_P, false);
1023:                lenient = props.getBoolean(LENIENT_P, true);
1024:                keep = props.getBoolean(KEEP_ALIVE_P, keep);
1025:                logger_class = props.getString(LOGGER_P, null);
1026:                factory_class = props
1027:                        .getString(CLIENT_FACTORY_P, factory_class);
1028:                shuffler_path = props.getString(SHUFFLER_PATH_P, null);
1029:                rootstr = props.getString(ROOT_P, null);
1030:                spacestr = props.getString(SPACE_P, null);
1031:                host = props.getString(HOST_P, defhost);
1032:                port = props.getInteger(PORT_P, port);
1033:                root_name = props.getString(ROOT_NAME_P, "root");
1034:                root_class = props.getString(ROOT_CLASS_P, null);
1035:                max_loaded_store = props.getInteger(MAX_LOADED_STORE_P,
1036:                        MAX_LOADED_STORE);
1037:                store_size_limit = props.getInteger(STORE_SIZE_LIMIT_P,
1038:                        STORE_SIZE_LIMIT);
1039:                sensitivity = props.getBoolean(FS_SENSITIVITY, true);
1040:                publicMethods = props.getStringArray(PUBLIC_P, publicMethods);
1041:                // Get client properties:
1042:                client_debug = props.getBoolean(CLIENT_DEBUG_P, client_debug);
1043:                request_time_out = props.getInteger(REQUEST_TIMEOUT_P,
1044:                        request_time_out);
1045:                connection_time_out = props.getInteger(KEEP_TIMEOUT_P,
1046:                        connection_time_out);
1047:                client_priority = props.getInteger(CLIENT_PRIORITY_P,
1048:                        client_priority);
1049:                client_bufsize = props.getInteger(CLIENT_BUFSIZE_P,
1050:                        client_bufsize);
1051:                // Check that a host name has been given:
1052:                if (host == null)
1053:                    throw new ServerHandlerInitException(this .getClass()
1054:                            .getName()
1055:                            + "[initializeProperties]: " + "[host] undefined.");
1056:                // Default the root directory to the current directory:
1057:                if (rootstr == null) {
1058:                    // Try the current directory as root:
1059:                    rootstr = System.getProperties().getProperty("user.dir",
1060:                            null);
1061:                    if (rootstr == null)
1062:                        throw new ServerHandlerInitException(this .getClass()
1063:                                .getName()
1064:                                + "[initializeProperties]:"
1065:                                + "[root] undefined.");
1066:                }
1067:                root_dir = new File(rootstr);
1068:                // Default the space directory to root/WWW
1069:                if (spacestr == null)
1070:                    space_dir = new File(root_dir, "WWW");
1071:                else
1072:                    space_dir = new File(spacestr);
1073:                // Help URL:
1074:                String propval = props.getString(DOCURL_P, null);
1075:                if (propval != null) {
1076:                    try {
1077:                        URL u = new URL(getURL(), propval);
1078:                        docurl = u.toExternalForm();
1079:                    } catch (Exception ex) {
1080:                    }
1081:                }
1082:                // Trash Dir
1083:                trashdir = props.getString(TRASHDIR_P, trashdir);
1084:                // checpointer url
1085:                checkurl = props.getString(CHECKURL_P, checkurl);
1086:            }
1087:
1088:            /**
1089:             * Register a property set to the server.
1090:             * @param propSet The property set to register.
1091:             */
1092:            public synchronized void registerPropertySet(PropertySet set) {
1093:                // Add this set to our known property set:
1094:                propSet.addElement(set);
1095:            }
1096:
1097:            /** 
1098:             * Enumerate all the registered property sets
1099:             * @return an enumeration of </code>PropertySet</code>
1100:             */
1101:            public Enumeration enumeratePropertySet() {
1102:                return propSet.elements();
1103:            }
1104:
1105:            /** 
1106:             * Get a property set matching a specific name 
1107:             * @return a Resource, the property set found
1108:             */
1109:            public Resource getPropertySet(String name) {
1110:                for (int i = 0; i < propSet.size(); i++) {
1111:                    PropertySet set = (PropertySet) propSet.elementAt(i);
1112:                    if (set.getIdentifier().equals(name))
1113:                        return set;
1114:                }
1115:                return null;
1116:            }
1117:
1118:            protected void initializePropertySets() {
1119:                registerPropertySet(new GeneralProp("general", this ));
1120:                registerPropertySet(new ConnectionProp("connection", this ));
1121:                registerPropertySet(new LoggingProp("logging", this ));
1122:            }
1123:
1124:            /**
1125:             * Get this server statistics.
1126:             */
1127:
1128:            public httpdStatistics getStatistics() {
1129:                return statistics;
1130:            }
1131:
1132:            /**
1133:             * Get this server properties.
1134:             */
1135:
1136:            public ObservableProperties getProperties() {
1137:                return props;
1138:            }
1139:
1140:            /**
1141:             * Is the underlying file-system case sensitive ?
1142:             * @return A boolean, <strong>true</strong> if file system is case 
1143:             * sensitive, <strong>false</strong> otherwise.
1144:             */
1145:            public boolean checkFileSystemSensitivity() {
1146:                return sensitivity;
1147:            }
1148:
1149:            /**
1150:             * Get the full URL of Jigsaw's documentation.
1151:             * @return A String encoded URL.
1152:             */
1153:            public String getDocumentationURL() {
1154:                return docurl;
1155:            }
1156:
1157:            /**
1158:             * Get the tracsh directory
1159:             */
1160:            public String getTrashDirectory() {
1161:                return trashdir;
1162:            }
1163:
1164:            /**
1165:             * Get the client's debug flags from the properties.
1166:             */
1167:            public final boolean getClientDebug() {
1168:                return client_debug;
1169:            }
1170:
1171:            /**
1172:             * Does this server wants clients to try keeping connections alive ?
1173:             */
1174:            public final boolean getClientKeepConnection() {
1175:                return keep;
1176:            }
1177:
1178:            /**
1179:             * Get the request allowed time slice from the properties.
1180:             */
1181:            public final int getRequestTimeOut() {
1182:                return request_time_out;
1183:            }
1184:
1185:            /**
1186:             * Get the connection allowed idle time from the properties.
1187:             */
1188:            public final int getConnectionTimeOut() {
1189:                return connection_time_out;
1190:            }
1191:
1192:            /**
1193:             * Get the client's threads priority from the properties.
1194:             */
1195:            public final int getClientThreadPriority() {
1196:                return client_priority;
1197:            }
1198:
1199:            /**
1200:             * Get the client's buffer size.
1201:             */
1202:            public final int getClientBufferSize() {
1203:                return client_bufsize;
1204:            }
1205:
1206:            /**
1207:             * Get this server host name.
1208:             */
1209:            public String getHost() {
1210:                return host;
1211:            }
1212:
1213:            /**
1214:             * Get this server port number.
1215:             */
1216:            public int getPort() {
1217:                return port;
1218:            }
1219:
1220:            /**
1221:             * Get the server current root resource.
1222:             */
1223:            public FramedResource getRoot() {
1224:                return root;
1225:            }
1226:
1227:            /**
1228:             * get the resource reference of the root resource of the server
1229:             */
1230:            public ResourceReference getRootReference() {
1231:                return root_reference;
1232:            }
1233:
1234:            /**
1235:             * Get the logger for that server.
1236:             * @return A Logger compatible instance, or <strong>null</strong> if 
1237:             * no logger specified.
1238:             */
1239:            public Logger getLogger() {
1240:                return logger;
1241:            }
1242:
1243:            /**
1244:             * Get the server's edit root resource.
1245:             * The edit root is the one that shows up by default when using JigAdmin
1246:             * It is named "root" in the interface.
1247:             * @return An HTTPResource.
1248:             */
1249:
1250:            public synchronized ResourceReference getEditRoot() {
1251:                if (editroot == null) {
1252:                    // Check for the appropriate property:
1253:                    String name = props.getString(EDIT_ROOT_P, null);
1254:                    if (name != null) {
1255:                        editroot = loadRoot(name);
1256:                    }
1257:                    if (editroot == null) {
1258:                        editroot = getRootReference();
1259:                    }
1260:                }
1261:                return editroot;
1262:            }
1263:
1264:            /**
1265:             * Get the server URL.
1266:             */
1267:            public URL getURL() {
1268:                if (url == null) {
1269:                    try {
1270:                        if (port != 80)
1271:                            url = new URL("http", host, port, "/");
1272:                        else
1273:                            url = new URL("http", host, "/");
1274:                    } catch (MalformedURLException ex) {
1275:                        throw new RuntimeException(
1276:                                "unable to build server's URL");
1277:                    }
1278:                }
1279:                return url;
1280:            }
1281:
1282:            /**
1283:             * Get the server software string.
1284:             */
1285:            public String getSoftware() {
1286:                return software;
1287:            }
1288:
1289:            /**
1290:             * Get the server local port
1291:             */
1292:            public int getLocalPort() {
1293:                return socket.getLocalPort();
1294:            }
1295:
1296:            /**
1297:             * Get this server identifier.
1298:             */
1299:            public String getIdentifier() {
1300:                return identifier;
1301:            }
1302:
1303:            /**
1304:             * Get the server inet address
1305:             * @return The INET address this server is listening to.
1306:             */
1307:            public InetAddress getInetAddress() {
1308:                return socket.getInetAddress();
1309:            }
1310:
1311:            /**
1312:             * Get this server root directory.
1313:             */
1314:            public File getRootDirectory() {
1315:                return root_dir;
1316:            }
1317:
1318:            /**
1319:             * Get this server space diretory
1320:             */
1321:            public File getSpaceDir() {
1322:                return space_dir;
1323:            }
1324:
1325:            /**
1326:             * Get this server config directory.
1327:             */
1328:            public File getConfigDirectory() {
1329:                File file = props.getFile(CONFIG_P, null);
1330:                return (file == null) ? new File(getRootDirectory(), "config")
1331:                        : file;
1332:            }
1333:
1334:            /**
1335:             * Get this server authentication directory.
1336:             */
1337:            public File getAuthDirectory() {
1338:                return new File(getConfigDirectory(), "auth");
1339:            }
1340:
1341:            /**
1342:             * Get this server store directory.
1343:             */
1344:            public File getStoreDirectory() {
1345:                return new File(getConfigDirectory(), "stores");
1346:            }
1347:
1348:            /**
1349:             * Get this server index directory
1350:             */
1351:            public File getIndexerDirectory() {
1352:                return new File(getConfigDirectory(), "indexers");
1353:            }
1354:
1355:            /**
1356:             * Get temp directory
1357:             */
1358:            public File getTempDirectory() {
1359:                return new File(getRootDirectory(), "tmp");
1360:            }
1361:
1362:            /**
1363:             * Clean the temp dir.
1364:             */
1365:            protected void cleanTempDirectory() {
1366:                org.w3c.util.IO.clean(getTempDirectory());
1367:            }
1368:
1369:            /**
1370:             * get the indexer catalog of this server 
1371:             */
1372:            public IndexersCatalog getIndexersCatalog() {
1373:                if (indexers == null)
1374:                    indexers = new IndexersCatalog(new ResourceContext(
1375:                            getDefaultContext()));
1376:                return indexers;
1377:            }
1378:
1379:            /**
1380:             * Get this server realm catalog.
1381:             */
1382:            public RealmsCatalog getRealmsCatalog() {
1383:                return realms;
1384:            }
1385:
1386:            /**
1387:             * Get this server resourcestore manager.
1388:             */
1389:            public ResourceStoreManager getResourceStoreManager() {
1390:                return manager;
1391:            }
1392:
1393:            /**
1394:             * Get this server resource space
1395:             */
1396:            public ResourceSpace getResourceSpace() {
1397:                return manager;
1398:            }
1399:
1400:            /**
1401:             * Get the default resource context for that server.
1402:             */
1403:            public ResourceContext getDefaultContext() {
1404:                return context;
1405:            }
1406:
1407:            /**
1408:             * Get the lenient value, tru if we are lenient in HTTP parsing
1409:             */
1410:            public boolean isLenient() {
1411:                return lenient;
1412:            }
1413:
1414:            /**
1415:             * Cleanup the resources associated with this server context.
1416:             * This method should only be called by the server thread itself, when
1417:             * it is requested to perform the cleanup.
1418:             * @param restart If <strong>true</strong> the server is restarted 
1419:             *     (reinitialized) straight away.
1420:             */
1421:
1422:            protected synchronized void cleanup(boolean restart) {
1423:                // Close the accepting socket:
1424:                try {
1425:                    socket.close();
1426:                    socket = null;
1427:                } catch (IOException ex) {
1428:                    errlog("[cleanup]: IOException while closing server socket.");
1429:                }
1430:                // FIXME temporary hack for clones
1431:                synchronized (instances) {
1432:                    // remove one instance
1433:                    instances[0]--; // @wplatzer
1434:                    if (factory != null)
1435:                        factory.shutdown(true);
1436:                    factory = null;
1437:                    if (manager != null && instances[0] == 0) // FIXME (shm)
1438:                        manager.shutdown();
1439:                    manager = null;
1440:                    if (shuffler != null)
1441:                        shuffler.shutdown();
1442:                    shuffler = null;
1443:                    // Unregister to property monitoring
1444:                    props.unregisterObserver(this );
1445:                    errlog("shutdown completed at: " + new Date() + ".");
1446:                    // Finally close the log
1447:                    if (logger != null && instances[0] == 0) // FIXME shm
1448:                        logger.shutdown();
1449:                    logger = null;
1450:                    // Release any other pointers:
1451:                    timer.stopEventManager();
1452:                    System.out.println(getIdentifier() + ": " + getURL()
1453:                            + " done.");
1454:                    System.out.flush();
1455:                    // Keep the data neede to reinit (in case needed)
1456:                    File init_propfile = props.getFile(PROPS_P, null);
1457:                    ObservableProperties init_props = props;
1458:                    String init_identifier = identifier;
1459:                    // Release pointed data:
1460:                    identifier = null;
1461:                    manager = null;
1462:                    factory = null;
1463:                    shuffler = null;
1464:                    // FIXME clones props      = null ;
1465:                    indexer = null;
1466:                    root = null;
1467:                    realms = null;
1468:                    logger = null;
1469:                    socket = null;
1470:                    timer = null;
1471:                    thread = null;
1472:                    url = null;
1473:                    restarting = false;
1474:                    finishing = false;
1475:                    if (restart) {
1476:                        try {
1477:                            instances[0]++; //FIXME clones
1478:                            initialize(shm, init_identifier, init_props);
1479:                            start();
1480:                        } catch (Exception ex) {
1481:                            // We really can't do more than this here:
1482:                            System.out.println("*** server restart failed.");
1483:                            ex.printStackTrace();
1484:                        }
1485:                    }
1486:                }
1487:            }
1488:
1489:            /**
1490:             * Shutdown the server properly.
1491:             * This methods shutdown the server, and clean-up all its associated 
1492:             * resources. If the current thread is not the server thread, it unblocks
1493:             * the server thread from its accept() call, and forces it to perform
1494:             * the rest of the shutdown operation itself.
1495:             * @see httpd#cleanup
1496:             */
1497:
1498:            public synchronized void shutdown() {
1499:                checkpoint();
1500:                errlog("shutdown inited...(save done)");
1501:                finishing = true;
1502:                try {
1503:                    Socket unlock = new Socket(host, port);
1504:                    unlock.close();
1505:                } catch (IOException ex) {
1506:                    errlog("[shutdown]: IOException while unblocking server thread.");
1507:                }
1508:                shm.removeServerHandler(this );
1509:                cleanTempDirectory();
1510:            }
1511:
1512:            /**
1513:             * Restart the server properly.
1514:             * This methods restarts the server. It cleans-up all its associated 
1515:             * resources, and reinitialize it from scratch. If the current thread is
1516:             * not the server thread, it unblocks
1517:             * the server thread from its accept() call, and forces it to perform
1518:             * the rest of the restart operation itself.
1519:             * @param reload_properties Should we reload the properties from the
1520:             *    property file, or should we just reinitialize from the current set
1521:             *    of properties.
1522:             * @see httpd#cleanup
1523:             */
1524:
1525:            public synchronized void restart() {
1526:                errlog("[restart]: inited !");
1527:                finishing = true;
1528:                restarting = true;
1529:                try {
1530:                    Socket unlock = new Socket(host, port);
1531:                    unlock.close();
1532:                } catch (IOException ex) {
1533:                    errlog("[restart]: IOException while unblocking server thread.");
1534:                }
1535:            }
1536:
1537:            /**
1538:             * Turn debugging on/off for this instance of httpd server.
1539:             * @param A boolean, true turns debugging on, flase turns it off.
1540:             */
1541:
1542:            public void debug(boolean onoff) {
1543:                tracep = onoff;
1544:            }
1545:
1546:            /**
1547:             * Emit a server trace. Traces are used solely for debugging purposes. You
1548:             * should either use <b>log</b> or <b>error</b> to report informations.
1549:             * @param client The client object which wants to report the trace.
1550:             * @param msg The trace message.
1551:             * @see httpd#log
1552:             */
1553:
1554:            public void trace(Client client, String msg) {
1555:                if (tracep && (logger != null))
1556:                    logger.trace(client, msg);
1557:            }
1558:
1559:            /**
1560:             * Emit a server trace, on behalf of the server itself.
1561:             * @param msg The trace the server wants to emit.
1562:             */
1563:            public void trace(String msg) {
1564:                if (tracep && (logger != null))
1565:                    logger.trace(msg);
1566:            }
1567:
1568:            /**
1569:             * Emit a log entry.
1570:             * @param client The client whose request is to be logged.
1571:             * @param request The request that has been handled.
1572:             * @param reply The emitted reply.
1573:             * @param nbytes The number of bytes emitted back to the client.
1574:             * @param duration The time it took to process the request.
1575:             */
1576:            public void log(Client client, Request request, Reply reply,
1577:                    int nbytes, long duration) {
1578:                if (logger != null)
1579:                    logger.log(request, reply, nbytes, duration);
1580:                statistics.updateStatistics(client, request, reply, nbytes,
1581:                        duration);
1582:            }
1583:
1584:            /**
1585:             * Emit a log message.
1586:             * @param msg The message to log.
1587:             */
1588:            public void log(String msg) {
1589:                logger.log(msg);
1590:            }
1591:
1592:            /**
1593:             * Emit a server error on behalf of some client object.
1594:             * @param client The client.
1595:             * @param msg The error message.
1596:             */
1597:            public void errlog(Client client, String msg) {
1598:                if (logger != null)
1599:                    logger.errlog(client, msg);
1600:            }
1601:
1602:            /**
1603:             * Emit an error on behalf of the server.
1604:             * @param msg The error message.
1605:             */
1606:
1607:            public void errlog(String msg) {
1608:                if (logger != null)
1609:                    logger.errlog("[" + identifier + "] " + msg);
1610:            }
1611:
1612:            /**
1613:             * The prefered form for reporting errors.
1614:             * @param from The object that emited the error.
1615:             * @param msg The error message.
1616:             */
1617:            public void errlog(Object from, String msg) {
1618:                if (logger != null)
1619:                    logger
1620:                            .errlog("[" + from.getClass().getName() + "]: "
1621:                                    + msg);
1622:            }
1623:
1624:            /**
1625:             * Another nice way of reporting errors from an HTTPResource.
1626:             * @param from The resource that trigered the error.
1627:             * @param msg The error message.
1628:             */
1629:            public void errlog(Resource from, String msg) {
1630:                if (logger != null)
1631:                    logger.errlog(from.getClass().getName() + "@"
1632:                            + from.unsafeGetURLPath() + ": " + msg);
1633:            }
1634:
1635:            /**
1636:             * Emit a fatal error.
1637:             * @param e Any exception that caused the error.
1638:             * @param msg Any additional message.
1639:             */
1640:            public void fatal(Exception e, String msg) {
1641:                System.out.println("*** Fatal Error, aborting");
1642:                System.out.println(this .getClass().getName() + ": " + msg);
1643:                e.printStackTrace();
1644:                throw new RuntimeException(msg);
1645:            }
1646:
1647:            /**
1648:             * Emit a fatal error.
1649:             * @param msg Any error message
1650:             */
1651:            public void fatal(String msg) {
1652:                System.out.println("*** Fatal error, aborting");
1653:                System.out.println(this .getClass().getName() + ": " + msg);
1654:                throw new RuntimeException(msg);
1655:            }
1656:
1657:            /**
1658:             * Emit a warning.
1659:             * Warnings are emited, typically if the configuration is inconsistent,
1660:             * and the server can continue its work.
1661:             * @param msg The warning message.
1662:             */
1663:            public void warning(String msg) {
1664:                System.out.println("*** Warning : " + msg);
1665:            }
1666:
1667:            /**
1668:             * Emit a warning.
1669:             * @param e Any exception.
1670:             * @param msg Any message.
1671:             */
1672:            public void warning(Exception e, String msg) {
1673:                System.out.println("*** Warning: " + msg);
1674:                e.printStackTrace();
1675:            }
1676:
1677:            /**
1678:             * Get a shuffler for this server's client.
1679:             * Whenever possible, we use a shuffler program to speed up communication
1680:             * with the client. This methods return whatever the server deems 
1681:             * appropriate for this client shuffler.
1682:             * @return A Shuffler instance, or <strong>null</strong>.
1683:             * @see org.w3c.jigsaw.http.Shuffler
1684:             */
1685:            public synchronized Shuffler getShuffler(Client client) {
1686:                return shuffler;
1687:            }
1688:
1689:            protected String getBanner() {
1690:                return "Jigsaw[" + version + "]";
1691:            }
1692:
1693:            public void run() {
1694:                // Emit some traces before starting up:
1695:                System.out.println(getBanner() + ": serving at " + getURL());
1696:                System.out.flush();
1697:                errlog("started at: " + new Date() + ".");
1698:                // Enter the evil loop:
1699:                while ((!finishing) && (socket != null)) {
1700:                    Socket ns = null;
1701:                    try {
1702:                        ns = socket.accept();
1703:                        ns.setTcpNoDelay(true);
1704:                    } catch (IOException e) {
1705:                        if (debug)
1706:                            e.printStackTrace();
1707:                        errlog("failed to accept incoming connection on "
1708:                                + socket);
1709:                        // just in case, as it may have been created.
1710:                        try {
1711:                            ns.close();
1712:                        } catch (Exception ex) {
1713:                        }
1714:                        ;
1715:                        ns = null;
1716:                    }
1717:                    if ((socket != null) && (ns != null) && (factory != null))
1718:                        factory.handleConnection(ns);
1719:                }
1720:                // Our socket has been closed, perform associated cleanup.
1721:                cleanup(restarting);
1722:            }
1723:
1724:            /**
1725:             * Perform the given request on behalf of this server.
1726:             * @param request The request to perform.
1727:             * @return A non-null Reply instance.
1728:             * @exception ProtocolException If some error occurs during processing the
1729:             * request.
1730:             * @exception ResourceException If a resource got a fatal error.
1731:             */
1732:
1733:            public ReplyInterface perform(RequestInterface req)
1734:                    throws ProtocolException, ResourceException {
1735:                Request request = (Request) req;
1736:                // This may be a server-wide request, this is an ugly hack in HTTP spec
1737:                if (request.getURL() == Request.THE_SERVER) {
1738:                    if (request.getMethod().equals("OPTIONS")) {
1739:                        HttpTokenList pub = null;
1740:                        synchronized (this ) {
1741:                            if (publicHeader == null)
1742:                                pub = HttpFactory.makeStringList(publicMethods);
1743:                            publicHeader = pub;
1744:                        }
1745:                        Reply reply = request.makeReply(HTTP.OK);
1746:                        if (pub != null) {
1747:                            reply.setHeaderValue(Reply.H_PUBLIC, pub);
1748:                        }
1749:                        reply.setContentLength(0);
1750:                        return reply;
1751:                    }
1752:                }
1753:                if (request.getMethod().equals("TRACE")) {
1754:                    // check if the resource can be proxied
1755:                    boolean doit = true;
1756:                    LookupState ls = new LookupState(request);
1757:                    LookupResult lr = new LookupResult(root
1758:                            .getResourceReference());
1759:                    try {
1760:                        if (root.lookup(ls, lr)) {
1761:                            ResourceReference target = lr.getTarget();
1762:                            if (target != null) {
1763:                                try {
1764:                                    // this is plain ugly and won't work for proxy
1765:                                    // not based on this resource
1766:                                    // do we need another way to to this?
1767:                                    FramedResource fr = (FramedResource) target
1768:                                            .lock();
1769:                                    Class cff = Class
1770:                                            .forName("org.w3c.jigsaw.proxy.ForwardFrame");
1771:                                    doit = (fr.getFrameReference(cff) == null);
1772:                                } catch (Exception ex) {
1773:                                    // fail miserably to the fallback
1774:                                } finally {
1775:                                    target.unlock();
1776:                                }
1777:                            }
1778:                        }
1779:                    } catch (Exception ex) {
1780:                    }
1781:                    ;
1782:                    if (doit) {
1783:                        Reply reply = request.makeReply(HTTP.OK);
1784:                        reply.setNoCache(); // don't cache this
1785:                        reply.setMaxAge(-1);
1786:                        // Dump the request as the body
1787:                        // Removed unused headers:
1788:                        // FIXME should be something else for chuncked stream
1789:                        ByteArrayOutputStream ba = new ByteArrayOutputStream();
1790:                        try {
1791:                            reply.setContentType(new MimeType("message/http"));
1792:                            request.dump(ba);
1793:                            reply.setContentLength(ba.size());
1794:                        } catch (Exception ex) {
1795:                            ex.printStackTrace();
1796:                        }
1797:                        reply.setStream(new ByteArrayInputStream(ba
1798:                                .toByteArray()));
1799:                        return reply;
1800:                    }
1801:                }
1802:                // Create a lookup state, and a lookup result:
1803:
1804:                ProtocolException error = null;
1805:                LookupState ls = null;
1806:                LookupResult lr = null;
1807:                // Run the lookup algorithm of root resource:
1808:                // catch exception to get error (FIXME)
1809:                try {
1810:                    lr = new LookupResult(root.getResourceReference());
1811:                    ls = new LookupState(request);
1812:
1813:                    if (root.lookup(ls, lr)) {
1814:                        if (lr.hasReply())
1815:                            return lr.getReply();
1816:                    }
1817:                } catch (ProtocolException ex) {
1818:                    error = ex;
1819:                } catch (Exception ex) {
1820:                    /*
1821:                     * We have a problem here, the error can be a configuration
1822:                     * or resource/extension problem, and it should be a 
1823:                     * 5xx error, or it is a client side error and it should be
1824:                     * a 4xx error, ex, try with "Authorization:" and it fails.
1825:                     * For now we will reply with a 400, but with a FIXME
1826:                     */
1827:                    Reply err = request.makeReply(HTTP.BAD_REQUEST);
1828:                    err
1829:                            .setContent("<html><head><title>Bad Request</title></head>\n"
1830:                                    + "<body><p>The server was not able to "
1831:                                    + "understand this request</p></body></html>");
1832:                    error = new ProtocolException(err);
1833:                }
1834:                // Let the target resource perform the method
1835:                ResourceReference target = lr.getTarget();
1836:                Reply reply = null;
1837:
1838:                ResourceFilter filters[] = lr.getFilters();
1839:                int infilter = 0;
1840:
1841:                if (error == null) {
1842:                    //call the ingoing filters:
1843:                    try {
1844:                        // temporary target resource !!! WARNING
1845:                        request.setTargetResource(target);
1846:                        if (filters != null) {
1847:                            for (; infilter < filters.length; infilter++) {
1848:                                if (filters[infilter] == null)
1849:                                    continue;
1850:                                reply = (Reply) filters[infilter]
1851:                                        .ingoingFilter(request, filters,
1852:                                                infilter);
1853:                                if (reply != null) {
1854:                                    return reply;
1855:                                }
1856:                            }
1857:                        }
1858:                    } catch (ProtocolException ex) {
1859:                        error = ex;
1860:                    }
1861:                    //perform the request:
1862:                    if ((error == null) && (target != null)) {
1863:                        request.setFilters(filters, infilter);
1864:                        request.setTargetResource(target);
1865:                        try {
1866:                            FramedResource res = (FramedResource) target.lock();
1867:                            reply = (Reply) res.perform(request);
1868:                            if (reply == null) {
1869:                                reply = request.makeReply(HTTP.NOT_FOUND);
1870:                                if (uri_error) {
1871:                                    reply
1872:                                            .setContent("<html><head><title>Not Found"
1873:                                                    + "</title></head>\n"
1874:                                                    + "<body><h1>Invalid"
1875:                                                    + " URL</h1><p>The URL <b>"
1876:                                                    + request.getURL()
1877:                                                    + "</b> that you requested is not"
1878:                                                    + " available "
1879:                                                    + " for this protocol.</body>\n"
1880:                                                    + "</html>");
1881:                                } else {
1882:                                    reply
1883:                                            .setContent("<html><head><title>Not Found"
1884:                                                    + "</title></head>\n"
1885:                                                    + "<body><h1>Invalid"
1886:                                                    + " URL</h1><p>The URL"
1887:                                                    + "</b> that you requested is not"
1888:                                                    + " available "
1889:                                                    + " for this protocol.</body>\n"
1890:                                                    + "</html>");
1891:                                }
1892:                                reply
1893:                                        .setContentType(org.w3c.www.mime.MimeType.TEXT_HTML);
1894:                            }
1895:                        } catch (InvalidResourceException ex) {
1896:                            //FIXME
1897:                            reply = request.makeReply(HTTP.NOT_FOUND);
1898:                            if (uri_error) {
1899:                                reply.setContent("<html><head><title>Not"
1900:                                        + " Found</title>"
1901:                                        + "</head><body><b>The URL <b>"
1902:                                        + request.getURL()
1903:                                        + "</b> that you requested is not "
1904:                                        + "available, "
1905:                                        + " probably deleted.</body></html>");
1906:                            } else {
1907:                                reply.setContent("<html><head><title>Not"
1908:                                        + " Found</title>"
1909:                                        + "</head><body><b>The URL"
1910:                                        + " that you requested is not "
1911:                                        + "available, "
1912:                                        + " probably deleted.</body></html>");
1913:                            }
1914:                            reply
1915:                                    .setContentType(org.w3c.www.mime.MimeType.TEXT_HTML);
1916:                        } finally {
1917:                            target.unlock();
1918:                        }
1919:                    } else {
1920:                        reply = request.makeReply(HTTP.NOT_FOUND);
1921:                        if (uri_error) {
1922:                            reply.setContent("<html><head>\n"
1923:                                    + "<title>Not Found</title></head>"
1924:                                    + "<body><h1>Invalid URL</h1><p>The URL"
1925:                                    + " <b>" + request.getURL()
1926:                                    + "</b> that you requested is not"
1927:                                    + " available "
1928:                                    + " on that server.</body></html>");
1929:                        } else {
1930:                            reply.setContent("<html><head>\n"
1931:                                    + "<title>Not Found</title></head>"
1932:                                    + "<body><h1>Invalid URL</h1><p>The URL"
1933:                                    + " that you requested is not"
1934:                                    + " available "
1935:                                    + " on that server.</body></html>");
1936:                        }
1937:                        reply
1938:                                .setContentType(org.w3c.www.mime.MimeType.TEXT_HTML);
1939:                    }
1940:                }
1941:                // call the outgoing filters:
1942:                if ((reply == null) || (reply.getStatus() != HTTP.DONE)) {
1943:                    if (error == null) {
1944:                        for (int i = infilter; --i >= 0;) {
1945:                            if (filters[i] == null)
1946:                                continue;
1947:                            Reply fr = (Reply) filters[i].outgoingFilter(
1948:                                    request, reply, filters, i);
1949:                            if (fr != null)
1950:                                return fr;
1951:                        }
1952:                    } else {
1953:                        // Make sure we always invoke appropriate filters:
1954:                        if (filters != null) {
1955:                            for (int i = filters.length; --i >= 0;) {
1956:                                if (filters[i] == null) {
1957:                                    continue;
1958:                                }
1959:                                Reply fr = (Reply) filters[i].exceptionFilter(
1960:                                        request, error, filters, i);
1961:                                if (fr != null) {
1962:                                    return fr;
1963:                                }
1964:                            }
1965:                        }
1966:                        reply = (Reply) error.getReply();
1967:                        if (reply == null) {
1968:                            reply = request
1969:                                    .makeReply(HTTP.INTERNAL_SERVER_ERROR);
1970:                            if (uri_error) {
1971:                                reply.setContent("<html><head>\n"
1972:                                        + "<title>Server Error</title>"
1973:                                        + "</head><body><h1>Invalid URL</h1>"
1974:                                        + "<p>The URL <b>" + request.getURL()
1975:                                        + "</b>: isn't available "
1976:                                        + " on that server.</body></html>");
1977:                            } else {
1978:                                reply.setContent("<html><head>\n"
1979:                                        + "<title>Server Error</title>"
1980:                                        + "</head><body><h1>Invalid URL</h1>"
1981:                                        + "<p>The URL" + " isn't available "
1982:                                        + " on that server.</body></html>");
1983:                            }
1984:                            reply
1985:                                    .setContentType(org.w3c.www.mime.MimeType.TEXT_HTML);
1986:                        }
1987:                    }
1988:                }
1989:                return reply;
1990:            }
1991:
1992:            protected boolean checkUpgrade(String id, ObservableProperties props) {
1993:                // Check for an upgrade:
1994:                int configvers = props.getInteger(httpd.VERSCOUNT_P, 1);
1995:                if (configvers < httpd.verscount) {
1996:                    System.err
1997:                            .println("*** Jigsaw needs upgrade from internal "
1998:                                    + "version " + configvers + " to "
1999:                                    + httpd.verscount);
2000:                    if (httpd.verscount == 4) {
2001:                        org.w3c.tools.resources.serialization.Serializer serializer = new org.w3c.tools.resources.serialization.xml.XMLSerializer();
2002:                        props
2003:                                .put(httpd.SERIALIZER_CLASS_P,
2004:                                        "org.w3c.tools.resources.serialization.xml.XMLSerializer");
2005:                        File propsfile = props.getFile(PROPS_P, null);
2006:                        Upgrader upgrader = new Upgrader(id,
2007:                                getConfigDirectory(), propsfile, serializer);
2008:                        props.put(httpd.VERSCOUNT_P, String
2009:                                .valueOf(httpd.verscount));
2010:                        props.put(httpd.SERVER_SOFTWARE_P, "Jigsaw/" + version);
2011:                        try {
2012:                            upgrader.upgrade(httpd.verscount);
2013:                            return true;
2014:                        } catch (Exception ex) {
2015:                            System.err.println(ex.getMessage());
2016:                            return false;
2017:                        }
2018:                    }
2019:                    return false;
2020:                }
2021:                return true;
2022:            }
2023:
2024:            /**
2025:             * Initialize a new HTTP server.
2026:             * The server wil first be initialized from the available properties,
2027:             * it will than startup, and finally run in its own thread.
2028:             * @param identifier The string identifying this server's occurence.
2029:             * @param props A set of properties to initialize from.
2030:             * @exception ServerHandlerInitException if unable to be initialized.
2031:             */
2032:
2033:            public void initialize(ServerHandlerManager shm, String identifier,
2034:                    ObservableProperties props)
2035:                    throws ServerHandlerInitException {
2036:                // Check for an optional upgrade of config files:
2037:                // checkUpgrade(shm, identifier, props);
2038:                this .shm = shm;
2039:                // Initialize from properties:
2040:                this .identifier = identifier;
2041:                this .props = props;
2042:                // with an explicit cast for buggy compilers
2043:                this .props.registerObserver((PropertyMonitoring) this );
2044:                initializeProperties();
2045:                if (!checkUpgrade(identifier, props))
2046:                    throw new ServerHandlerInitException("Upgrade failed.");
2047:                // Create the socket, and run the server:
2048:                initializeServerSocket();
2049:            }
2050:
2051:            /**
2052:             * start the server
2053:             * it will than startup, and finally run in its own thread.
2054:             */
2055:
2056:            public void start() throws ServerHandlerInitException {
2057:                if (!isAClone) {
2058:                    // Create the default resource context (shared by all resources):
2059:                    this .context = new ResourceContext(this );
2060:                    //FIXME
2061:                    // Create the resource store manager
2062:                    initializeResourceSpace(identifier, root_class, props
2063:                            .getString(EDIT_ROOT_P, root_name), props
2064:                            .getString(SERIALIZER_CLASS_P, null),
2065:                            max_loaded_store);
2066:                    this .context.setSpace(getResourceSpace());
2067:                    // Create the resource indexer object
2068:                    initializeIndexer();
2069:                    // Resurect this server root entity:
2070:                    initializeRootResource();
2071:                    // Resurect the realms catalog
2072:                    initializeRealmsCatalog();
2073:                    // Initialize property sets
2074:                    initializePropertySets();
2075:                    // Create this server event manager 
2076:                    initializeEventManager();
2077:                    // Initialize the logger object:
2078:                    initializeLogger();
2079:                    // Initialize the shuffler object:
2080:                    if (shuffler_path != null) {
2081:                        try {
2082:                            this .shuffler = new Shuffler(shuffler_path);
2083:                        } catch (Error e) {
2084:                            warning("unable to launch shuffler to "
2085:                                    + shuffler_path + ": " + e.getMessage());
2086:                            this .shuffler = null;
2087:                        } catch (RuntimeException e) {
2088:                            warning(e, "unable to launch shuffler to "
2089:                                    + shuffler_path + ": " + e.getMessage());
2090:                            this .shuffler = null;
2091:                        }
2092:                    }
2093:                    if (this .shuffler != null)
2094:                        trace("using shuffler at: " + shuffler_path);
2095:                    // startup classes
2096:                    loadStartupClasses();
2097:                    // Yeah, now start:
2098:                    this .thread.start();
2099:                } else {
2100:                    httpd mainServ = (httpd) shm.lookupServerHandler(masterID);
2101:                    this .context = mainServ.getDefaultContext();
2102:                    this .realms = mainServ.realms;
2103:                    this .manager = mainServ.manager;
2104:                    // We basically re-use:
2105:                    // - the master indexer
2106:                    // - the master realms catalog
2107:                    // FIXED no need to use the same logger! - the master logger:
2108:                    // Initialize the logger object:
2109:                    initializeLogger();
2110:                    // Resurect this server root entity:
2111:                    initializeRootResource();
2112:                    // We use our own event manager
2113:                    initializeEventManager();
2114:                    // Yeah, now start:
2115:                    this .thread.start();
2116:                }
2117:            }
2118:
2119:            /**
2120:             * clone this server
2121:             * @exception ServerHandlerInitException if unable to be initialized.
2122:             */
2123:            public ServerHandler clone(ServerHandlerManager shm, String id,
2124:                    ObservableProperties props)
2125:                    throws ServerHandlerInitException {
2126:                // Clone this master server:
2127:                httpd server = null;
2128:                try {
2129:                    server = (httpd) clone();
2130:                } catch (CloneNotSupportedException ex) {
2131:                    throw new ServerHandlerInitException(this .getClass()
2132:                            .getName()
2133:                            + ": clone not supported !");
2134:                }
2135:                server.shm = shm;
2136:                // Nullify some of the cached instance variables:
2137:                server.url = null;
2138:                // Initialize 
2139:                server.masterID = server.identifier;
2140:                server.identifier = id;
2141:                server.props = props;
2142:                server.props.registerObserver((PropertyMonitoring) server);
2143:                server.initializeProperties();
2144:                server.initializeServerSocket();
2145:                server.isAClone = true;
2146:                return server;
2147:            }
2148:
2149:            /**
2150:             * get this server config resource
2151:             */
2152:            public ResourceReference getConfigResource() {
2153:                if (rr_configResource == null) {
2154:                    configResource = new ConfigResource(this );
2155:                    rr_configResource = new DummyResourceReference(
2156:                            configResource);
2157:                }
2158:                return rr_configResource;
2159:            }
2160:
2161:            /**
2162:             * Give the status of this class as a partial HTML text which will be added
2163:             * into a block level element
2164:             * @return a String, the generated HTML
2165:             */
2166:            public String getHTMLStatus() {
2167:                StringBuffer sb = new StringBuffer();
2168:                if (factory instanceof  Status) {
2169:                    sb.append(((Status) factory).getHTMLStatus());
2170:                }
2171:                sb.append(manager.getHTMLStatus());
2172:                return sb.toString();
2173:            }
2174:
2175:            /**
2176:             * Create a new server instance in this process.
2177:             * @param identifier The server's identifier.
2178:             * @param props The server properties.
2179:             */
2180:            public httpd() {
2181:                super ();
2182:            }
2183:
2184:            /**
2185:             * this server's usage
2186:             */
2187:            public static void usage() {
2188:                PrintStream o = System.out;
2189:
2190:                o.println("usage: httpd [OPTIONS]");
2191:                o.println("-id <id>          : server identifier.");
2192:                o
2193:                        .println("-port <number>    : listen on the given port number.");
2194:                o
2195:                        .println("-host <host>      : full name of host running the server.");
2196:                o.println("-root <directory> : root directory of server.");
2197:                o
2198:                        .println("-space <directory>: space directory exported by server");
2199:                o.println("-p     <propfile> : property file to read.");
2200:                o.println("-trace            : turns debugging on.");
2201:                o.println("-config           : config directory to use.");
2202:                o
2203:                        .println("-maxstores <int>  : Max number of stores in memory.");
2204:                System.exit(1);
2205:            }
2206:
2207:            /**
2208:             * debugging main
2209:             */
2210:            public static void main(String args[]) {
2211:                Integer cmdport = null;
2212:                String cmdhost = null;
2213:                String cmdroot = null;
2214:                String cmdspace = null;
2215:                String cmdprop = null;
2216:                String cmdid = "http-server";
2217:                String cmdconfig = "config";
2218:                Boolean cmdtrace = null;
2219:                boolean noupgrade = false;
2220:                String maxstores = null;
2221:
2222:                // Parse command line options:
2223:                for (int i = 0; i < args.length; i++) {
2224:                    if (args[i].equals("-port")) {
2225:                        try {
2226:                            cmdport = new Integer(args[++i]);
2227:                        } catch (NumberFormatException ex) {
2228:                            System.out.println("invalid port number ["
2229:                                    + args[i] + "]");
2230:                            System.exit(1);
2231:                        }
2232:                    } else if (args[i].equals("-id") && (i + 1 < args.length)) {
2233:                        cmdid = args[++i];
2234:                    } else if (args[i].equals("-maxstores")
2235:                            && (i + 1 < args.length)) {
2236:                        maxstores = args[++i];
2237:                    } else if (args[i].equals("-host") && (i + 1 < args.length)) {
2238:                        cmdhost = args[++i];
2239:                    } else if (args[i].equals("-root") && (i + 1 < args.length)) {
2240:                        cmdroot = args[++i];
2241:                    } else if (args[i].equals("-space")
2242:                            && (i + 1 < args.length)) {
2243:                        cmdspace = args[++i];
2244:                    } else if (args[i].equals("-p") && (i + 1 < args.length)) {
2245:                        cmdprop = args[++i];
2246:                    } else if (args[i].equals("-trace")) {
2247:                        cmdtrace = Boolean.TRUE;
2248:                    } else if (args[i].equals("?") || args[i].equals("-help")) {
2249:                        usage();
2250:                    } else if (args[i].equals("-config")
2251:                            && (i + 1 < args.length)) {
2252:                        cmdconfig = args[++i];
2253:                    } else if (args[i].equals("-noupgrade")) {
2254:                        noupgrade = true;
2255:                    } else {
2256:                        continue;
2257:                        // System.out.println ("unknown option: ["+args[i]+"]") ;
2258:                        // System.exit (1) ;
2259:                    }
2260:                }
2261:                // Get the properties for this server:
2262:                ObservableProperties props = null;
2263:                props = new ObservableProperties(System.getProperties());
2264:                // Get the root and configuration directories:
2265:                File root = ((cmdroot == null) ? new File(props.getProperty(
2266:                        "user.dir", null)) : new File(cmdroot));
2267:                File config = new File(root, cmdconfig);
2268:                // Locate the property file:
2269:                if (cmdprop == null) {
2270:                    // Try to guess it, cause it is really required:
2271:                    File guess = new File(config, cmdid + ".props");
2272:                    if (!guess.exists())
2273:                        // A hack for smooth upgrade from 1.0alpha3 to greater:
2274:                        guess = new File(config, "httpd.props");
2275:                    cmdprop = guess.getAbsolutePath();
2276:                }
2277:                if (cmdprop != null) {
2278:                    System.out.println("loading properties from: " + cmdprop);
2279:                    try {
2280:                        File propfile = new File(cmdprop);
2281:                        props.load(new FileInputStream(propfile));
2282:                        props.put(PROPS_P, propfile.getAbsolutePath());
2283:                    } catch (FileNotFoundException ex) {
2284:                        System.out.println("Unable to load properties: "
2285:                                + cmdprop);
2286:                        System.out.println("\t" + ex.getMessage());
2287:                        System.exit(1);
2288:                    } catch (IOException ex) {
2289:                        System.out.println("Unable to load properties: "
2290:                                + cmdprop);
2291:                        System.out.println("\t" + ex.getMessage());
2292:                        System.exit(1);
2293:                    }
2294:                    System.setProperties(props);
2295:                }
2296:                // Check for an upgrade:
2297:                int configvers = props.getInteger(httpd.VERSCOUNT_P, 1);
2298:                if (configvers < httpd.verscount) {
2299:                    System.err
2300:                            .println("+ Jigsaw needs upgrade from internal version "
2301:                                    + configvers + " to " + httpd.verscount);
2302:                    if (noupgrade) {
2303:                        System.err
2304:                                .println("+ Jigsaw cannot run in that version.");
2305:                        System.exit(1);
2306:                    }
2307:                    // upgrade(configvers, httpd.verscount, args);
2308:                    return;
2309:                }
2310:                // Override properties with our command line options:
2311:                if (cmdport != null)
2312:                    props.put(PORT_P, cmdport.toString());
2313:                if (cmdhost != null)
2314:                    props.put(HOST_P, cmdhost);
2315:                if (cmdroot != null)
2316:                    props.put(ROOT_P, root.getAbsolutePath());
2317:                if (cmdconfig != null)
2318:                    props.put(CONFIG_P, config.getAbsolutePath());
2319:                if (cmdspace != null)
2320:                    props.put(SPACE_P, cmdspace);
2321:                if (cmdtrace != null) {
2322:                    props.put(TRACE_P, "true");
2323:                    props.put(CLIENT_DEBUG_P, "true");
2324:                }
2325:                if (maxstores != null)
2326:                    props.put(MAX_LOADED_STORE_P, maxstores);
2327:
2328:                // Install security manager if needed:
2329:                if (Boolean.getBoolean(USE_SM_P)) {
2330:                    SecurityManager sm = new httpdSecurityManager();
2331:                    System.setSecurityManager(sm);
2332:                }
2333:                // Run the server:
2334:                try {
2335:                    httpd server = new httpd();
2336:                    server.initialize(null, cmdid, props);
2337:                } catch (Exception e) {
2338:                    System.out.println("*** [httpd]: fatal error, exiting !");
2339:                    e.printStackTrace();
2340:                }
2341:            }
2342:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.