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


001:        // CgiFrame.java
002:        // $Id: CgiFrame.java,v 1.19 2003/04/30 20:08:23 ylafon Exp $
003:        // (c) COPYRIGHT MIT and INRIA, 1996.
004:        // Please first read the full copyright statement in file COPYRIGHT.html
005:
006:        package org.w3c.jigsaw.frames;
007:
008:        import java.io.File;
009:        import java.io.IOException;
010:        import java.io.InputStream;
011:        import java.io.OutputStream;
012:        import java.io.PrintStream;
013:        import java.io.InputStreamReader;
014:        import java.io.BufferedReader;
015:
016:        import java.util.Enumeration;
017:        import java.util.Hashtable;
018:        import java.util.Vector;
019:
020:        import java.net.InetAddress;
021:        import java.net.MalformedURLException;
022:        import java.net.URL;
023:
024:        import org.w3c.tools.resources.Attribute;
025:        import org.w3c.tools.resources.AttributeHolder;
026:        import org.w3c.tools.resources.AttributeRegistry;
027:        import org.w3c.tools.resources.BooleanAttribute;
028:        import org.w3c.tools.resources.FileResource;
029:        import org.w3c.tools.resources.FramedResource;
030:        import org.w3c.tools.resources.InvalidParentException;
031:        import org.w3c.tools.resources.LookupResult;
032:        import org.w3c.tools.resources.LookupState;
033:        import org.w3c.tools.resources.PropertiesAttribute;
034:        import org.w3c.tools.resources.ProtocolException;
035:        import org.w3c.tools.resources.Resource;
036:        import org.w3c.tools.resources.ResourceException;
037:        import org.w3c.tools.resources.ResourceFrame;
038:        import org.w3c.tools.resources.ServerInterface;
039:        import org.w3c.tools.resources.StringArrayAttribute;
040:        import org.w3c.tools.resources.StringAttribute;
041:
042:        import org.w3c.tools.resources.ProtocolException;
043:
044:        import org.w3c.www.mime.MimeHeaderHolder;
045:        import org.w3c.www.mime.MimeParser;
046:        import org.w3c.www.mime.MimeParserException;
047:        import org.w3c.www.mime.MimeParserFactory;
048:        import org.w3c.www.mime.MimeType;
049:
050:        import org.w3c.jigsaw.http.Client;
051:        import org.w3c.jigsaw.http.HTTPException;
052:        import org.w3c.jigsaw.http.Reply;
053:        import org.w3c.jigsaw.http.Request;
054:        import org.w3c.jigsaw.http.httpd;
055:
056:        import org.w3c.www.http.HTTP;
057:        import org.w3c.www.http.HeaderDescription;
058:        import org.w3c.www.http.HttpEntityMessage;
059:        import org.w3c.www.http.HttpEntityTag;
060:        import org.w3c.www.http.HttpMessage;
061:        import org.w3c.www.http.HttpReplyMessage;
062:        import org.w3c.www.http.HttpRequestMessage;
063:
064:        import org.w3c.jigsaw.auth.AuthFilter;
065:        import org.w3c.util.ArrayDictionary;
066:
067:        /**
068:         * Parsing the CGI output - The CGIHeaderHolder, to hold CGI headers.
069:         */
070:        class CGIHeaderHolder implements  MimeHeaderHolder {
071:            // Status and Location deserve special treatments:
072:            String status = null;
073:            String location = null;
074:            // Anyway, he is going to pay for using CGI
075:            Hashtable headers = null;
076:            // The MIME parse we are attached to:
077:            MimeParser parser = null;
078:
079:            /**
080:             * The parsing is now about to start, take any appropriate action.
081:             * This hook can return a <strong>true</strong> boolean value to enforce
082:             * the MIME parser into transparent mode (eg the parser will <em>not</em>
083:             * try to parse any headers.
084:             * <p>This hack is primarily defined for HTTP/0.9 support, it might
085:             * also be usefull for other hacks.
086:             * @param parser The Mime parser.
087:             * @return A boolean <strong>true</strong> if the MimeParser shouldn't
088:             * continue the parsing, <strong>false</strong> otherwise.
089:             * @exception IOException if an IO error occurs.
090:             */
091:
092:            public boolean notifyBeginParsing(MimeParser parser)
093:                    throws IOException {
094:                return false;
095:            }
096:
097:            /**
098:             * All the headers have been parsed, take any appropriate actions.
099:             * @param parser The Mime parser.
100:             * @exception IOException if an IO error occurs.
101:             */
102:
103:            public void notifyEndParsing(MimeParser parser) throws IOException {
104:                return;
105:            }
106:
107:            /**
108:             * A new header has been emited by the script.
109:             * If the script is not an NPH, then it <strong>must</strong> at least
110:             * emit one header, so we are safe here, although people may not be safe 
111:             * against the spec.
112:             * @param name The header name.
113:             * @param buf The header bytes.
114:             * @param off The begining of the value bytes  in above buffer.
115:             * @param len The length of the value bytes  in above buffer.
116:             * @exception MimeParserException if parsing failed.
117:             */
118:
119:            public void notifyHeader(String name, byte buf[], int off, int len)
120:                    throws MimeParserException {
121:                if (name.equalsIgnoreCase("status")) {
122:                    status = new String(buf, 0, off, len);
123:                } else if (name.equalsIgnoreCase("location")) {
124:                    location = new String(buf, 0, off, len);
125:                } else {
126:                    String extraval = new String(buf, 0, off, len);
127:                    if (headers == null) {
128:                        headers = new Hashtable(11);
129:                    } else {
130:                        String val = (String) headers.get(name.toLowerCase());
131:                        if (val != null)
132:                            extraval = val + "," + extraval;
133:                    }
134:                    headers.put(name.toLowerCase(), extraval);
135:                }
136:            }
137:
138:            /**
139:             * Get the status emited by the script.
140:             */
141:
142:            public String getStatus() {
143:                return status;
144:            }
145:
146:            /**
147:             * Get the location header value emited by the script.
148:             */
149:
150:            public String getLocation() {
151:                return location;
152:            }
153:
154:            /**
155:             * Get any header value (except status and location).
156:             * @param name The name of the header to fetch.
157:             * @return The string value of requested header, or <strong>null</strong>
158:             * if header was not defined.
159:             */
160:
161:            public String getValue(String name) {
162:                return (headers == null) ? null : (String) headers.get(name);
163:            }
164:
165:            /**
166:             * Enumerate the headers defined by the holder.
167:             * @return A enumeration of header names, or <strong>null</strong> if no
168:             * header is defined.
169:             */
170:
171:            public Enumeration enumerateHeaders() {
172:                if (headers == null)
173:                    return null;
174:                return headers.keys();
175:            }
176:
177:            /**
178:             * Get the remaining output of the stream.
179:             * This should be called only once header parsing is done.
180:             */
181:
182:            public InputStream getInputStream() {
183:                return parser.getInputStream();
184:            }
185:
186:            CGIHeaderHolder(MimeParser parser) {
187:                this .parser = parser;
188:            }
189:
190:        }
191:
192:        /**
193:         * Parsing the CGI output - Always create a CGIHeaderHolder.
194:         */
195:
196:        class CGIHeaderHolderFactory implements  MimeParserFactory {
197:
198:            /**
199:             * Create a new header holder to hold the parser's result.
200:             * @param parser The parser that has something to parse.
201:             * @return A MimeParserHandler compliant object.
202:             */
203:
204:            public MimeHeaderHolder createHeaderHolder(MimeParser parser) {
205:                return new CGIHeaderHolder(parser);
206:            }
207:
208:            CGIHeaderHolderFactory() {
209:            }
210:
211:        }
212:
213:        /**
214:         * A simple process feeder class.
215:         */
216:
217:        class ProcessFeeder extends Thread {
218:            Process proc = null;
219:            OutputStream out = null;
220:            InputStream in = null;
221:            int count = -1;
222:
223:            public void run() {
224:                try {
225:                    byte buffer[] = new byte[4096];
226:                    int got = -1;
227:
228:                    // Send the data to the target process:
229:                    if (count >= 0) {
230:                        while ((count > 0) && ((got = in.read(buffer)) > 0)) {
231:                            out.write(buffer, 0, got);
232:                            count -= got;
233:                        }
234:                    } else {
235:                        while ((got = in.read(buffer)) > 0) {
236:                            out.write(buffer, 0, got);
237:                        }
238:                    }
239:                } catch (Exception e) {
240:                    System.out.println("ProcessFeeder: caught exception !");
241:                    e.printStackTrace();
242:                } finally {
243:                    // Clean up the process:
244:                    try {
245:                        out.flush();
246:                    } catch (IOException ex) {
247:                    }
248:                    try {
249:                        out.close();
250:                    } catch (IOException ex) {
251:                    }
252:                    try {
253:                        proc.waitFor();
254:                    } catch (Exception ex) {
255:                    }
256:                }
257:            }
258:
259:            ProcessFeeder(Process proc, InputStream in) {
260:                this (proc, in, -1);
261:            }
262:
263:            ProcessFeeder(Process proc, InputStream in, int count) {
264:                this .proc = proc;
265:                this .out = proc.getOutputStream();
266:                this .in = in;
267:                this .count = count;
268:            }
269:        }
270:
271:        /**
272:         * Handle CGI error stream
273:         */
274:        class ProcessErrorReader extends Thread {
275:            BufferedReader r = null;
276:
277:            public void run() {
278:                String errline = null;
279:                try {
280:                    errline = r.readLine();
281:                    if (errline != null) {
282:                        System.err.println("*** CgiError: " + errline);
283:                    }
284:                } catch (Exception ex) {
285:                } finally {
286:                    try {
287:                        r.close();
288:                    } catch (IOException ioex) {
289:                    }
290:                }
291:            }
292:
293:            ProcessErrorReader(Process proc) {
294:                r = new BufferedReader(new InputStreamReader(proc
295:                        .getErrorStream()));
296:            }
297:        }
298:
299:        /**
300:         * Handle CGI scripts.
301:         */
302:        public class CgiFrame extends HTTPFrame {
303:
304:            private final static String STATE_EXTRA_PATH = "org.w3c.jigsaw.frames.CgiFrame.extraPath";
305:
306:            /**
307:             * Attribute index - The interpreter to use, if any.
308:             */
309:            protected static int ATTR_INTERPRETER = -1;
310:            /**
311:             * Attribute index - The array of string that makes the command to run.
312:             */
313:            protected static int ATTR_COMMAND = -1;
314:            /**
315:             * Attribute index - Does the script takes care of its headers ?
316:             */
317:            protected static int ATTR_NOHEADER = -1;
318:            /**
319:             * Attribute index - Does the script generates the form on GET ?
320:             */
321:            protected static int ATTR_GENERATES_FORM = -1;
322:            /**
323:             * Attribute index - Do DNS, to fill in REMOTE_HOST env var.
324:             */
325:            protected static int ATTR_REMOTE_HOST = -1;
326:            /**
327:             * Attribute index - Turn the script in debug mode.
328:             */
329:            protected static int ATTR_CGI_DEBUG = -1;
330:            /**
331:             * Attribute index - Additional environment vars
332:             */
333:            protected static int ATTR_ENV = -1;
334:
335:            static {
336:                Attribute a = null;
337:                Class cls = null;
338:                try {
339:                    cls = Class.forName("org.w3c.jigsaw.frames.CgiFrame");
340:                } catch (Exception ex) {
341:                    ex.printStackTrace();
342:                    System.exit(1);
343:                }
344:                // The interpreter attribute:
345:                a = new StringAttribute("interpreter", null, Attribute.EDITABLE);
346:                ATTR_INTERPRETER = AttributeRegistry.registerAttribute(cls, a);
347:                // The command attribute:
348:                a = new StringArrayAttribute("command", null,
349:                        Attribute.MANDATORY | Attribute.EDITABLE);
350:                ATTR_COMMAND = AttributeRegistry.registerAttribute(cls, a);
351:                // The noheader attribute:
352:                a = new BooleanAttribute("noheader", Boolean.FALSE,
353:                        Attribute.EDITABLE);
354:                ATTR_NOHEADER = AttributeRegistry.registerAttribute(cls, a);
355:                // The generates form attribute
356:                a = new BooleanAttribute("generates-form", Boolean.TRUE,
357:                        Attribute.EDITABLE);
358:                ATTR_GENERATES_FORM = AttributeRegistry.registerAttribute(cls,
359:                        a);
360:                // Registerr the DODNS attribute.
361:                a = new BooleanAttribute("remote-host", null,
362:                        Attribute.EDITABLE);
363:                ATTR_REMOTE_HOST = AttributeRegistry.registerAttribute(cls, a);
364:                // Register the debug mode flag:
365:                a = new BooleanAttribute("cgi-debug", Boolean.FALSE,
366:                        Attribute.EDITABLE);
367:                ATTR_CGI_DEBUG = AttributeRegistry.registerAttribute(cls, a);
368:                // The env attribute:
369:                a = new PropertiesAttribute("environment", null,
370:                        Attribute.EDITABLE);
371:                ATTR_ENV = AttributeRegistry.registerAttribute(cls, a);
372:            }
373:
374:            /**
375:             * Get the interpreter to use to execute the script.
376:             * This is most usefull for operating systems that don't have a
377:             * <code>!#</code> convention ala UNIX.
378:             * @return The interpreter to run the script.
379:             */
380:
381:            public String getInterpreter() {
382:                return getString(ATTR_INTERPRETER, null);
383:            }
384:
385:            /**
386:             * Get the command string array.
387:             */
388:
389:            public String[] getCommand() {
390:                return (String[]) getValue(ATTR_COMMAND, null);
391:            }
392:
393:            public ArrayDictionary getUserEnv() {
394:                return (ArrayDictionary) getValue(ATTR_ENV, null);
395:            }
396:
397:            /**
398:             * Get the noheader flag.
399:             * @return The boolean value of the noheader flag.
400:             */
401:
402:            public boolean checkNoheaderFlag() {
403:                return getBoolean(ATTR_NOHEADER, false);
404:            }
405:
406:            /**
407:             * Get the generates form flag.
408:             * @return The boolean value of the generates form flag.
409:             */
410:
411:            public boolean checkGeneratesFormFlag() {
412:                return getBoolean(ATTR_GENERATES_FORM, true);
413:            }
414:
415:            /**
416:             * Get the remote host attribute value.
417:             * If turned on, this flag will enable the REMOTE_HOST env var computation.
418:             * @return A boolean.
419:             */
420:
421:            public boolean checkRemoteHost() {
422:                return getBoolean(ATTR_REMOTE_HOST, false);
423:            }
424:
425:            /**
426:             * Get the CGI debug flag.
427:             * @return The boolean value of the CGI debug flag.
428:             */
429:
430:            public boolean checkCgiDebug() {
431:                return getBoolean(ATTR_CGI_DEBUG, false);
432:            }
433:
434:            /**
435:             * Turn the given header name into it's env var canonical name.
436:             * This guy is crazy enough to run CGI scripts, he can pay for that 
437:             * overhead.
438:             * @param name The header name.
439:             * @return A String giving the official env variable name for that header.
440:             */
441:
442:            public String getEnvName(String name) {
443:                int sl = name.length();
444:                StringBuffer sb = new StringBuffer(5 + sl);
445:                sb.append("HTTP_");
446:                for (int i = 0; i < sl; i++) {
447:                    char ch = name.charAt(i);
448:                    sb.append((ch == '-') ? '_' : Character.toUpperCase(ch));
449:                }
450:                return sb.toString();
451:            }
452:
453:            /**
454:             * Get this resource Etag
455:             * @return an instance of HttpEntityTag, or <strong>null</strong> if not
456:             *    defined.
457:             */
458:            public HttpEntityTag getETag() {
459:                if (etag == null) {
460:                    HttpEntityTag netag = super .getETag();
461:                    if (netag != null) {
462:                        etag.setWeak(true);
463:                    }
464:                }
465:                return etag;
466:            }
467:
468:            /**
469:             * Handle the CGI script output.
470:             * This methods handles the CGI script output. Depending on the
471:             * value of the <strong>noheader</strong> attribute it either:
472:             * <ul>
473:             * <li>Sends back the script output directly,</li>
474:             * <li>Parses the script output, looking for a status header or a 
475:             * location header, or a content-length header, or any combination
476:             * of those three.
477:             * </ul>
478:             * @param process The underlying CGI process.
479:             * @param request The processed request.
480:             * @exception ProtocolException If an HTTP error 
481:             * should be sent back to the client.
482:             */
483:
484:            protected Reply handleCGIOutput(Process process, Request request)
485:                    throws ProtocolException {
486:                // first, take care of error stream
487:                (new ProcessErrorReader(process)).start();
488:                // No header script don't deserve attention:
489:                if (checkNoheaderFlag()) {
490:                    Reply reply = request.makeReply(HTTP.NOHEADER);
491:                    reply.setStream(process.getInputStream());
492:                    return reply;
493:                }
494:                // Check for debugging mode:
495:                if (checkCgiDebug()) {
496:                    Reply reply = request.makeReply(HTTP.OK);
497:                    reply.setContentType(MimeType.TEXT_PLAIN);
498:                    reply.setStream(process.getInputStream());
499:                    return reply;
500:                }
501:                // We MUST parse at least one header:
502:                MimeParser p = new MimeParser(process.getInputStream(),
503:                        new CGIHeaderHolderFactory());
504:                Reply reply = null;
505:                try {
506:                    CGIHeaderHolder h = (CGIHeaderHolder) p.parse();
507:                    // Check for a status code:
508:                    String svalue = h.getStatus();
509:                    String location = h.getLocation();
510:                    if (svalue != null) {
511:                        int status = -1;
512:                        try {
513:                            String _st = svalue.trim();
514:                            int _space = _st.indexOf(' ');
515:                            if (_space != -1) {
516:                                _st = _st.substring(0, _space);
517:                            }
518:                            status = Integer.parseInt(_st);
519:                        } catch (Exception ex) {
520:                            // This script has emited an invalid status line:
521:                            String msg = ("Emited an invalid status line ["
522:                                    + svalue + "].");
523:                            getServer().errlog(this , msg);
524:                            // Throw an HTTPException:
525:                            reply = request
526:                                    .makeReply(HTTP.INTERNAL_SERVER_ERROR);
527:                            reply
528:                                    .setContent("CGI script emited invalid status.");
529:                            throw new HTTPException(reply);
530:                        }
531:                        // we will use the default for this frame, but remove
532:                        // the length calculated from the script size.
533:                        reply = createDefaultReply(request, status);
534:                        reply.setContentLength(-1);
535:                    } else {
536:                        // No status code available, any location header ?
537:                        if (location != null) {
538:                            reply = request.makeReply(HTTP.FOUND);
539:                        } else {
540:                            reply = createDefaultReply(request, HTTP.OK);
541:                            reply.setContentLength(-1);
542:                        }
543:                    }
544:                    // Set up the location header if needed:
545:                    if (location != null) {
546:                        try {
547:                            reply
548:                                    .setLocation(new URL(getURL(request),
549:                                            location));
550:                        } catch (MalformedURLException ex) {
551:                            // This should really not happen:
552:                            getServer().errlog(
553:                                    this ,
554:                                    "unable to create location url " + location
555:                                            + " in base " + getURL(request));
556:                        }
557:                    }
558:                    // And then, the remaining headers:
559:                    Enumeration e = h.enumerateHeaders();
560:                    if (e != null) {
561:                        while (e.hasMoreElements()) {
562:                            String hname = (String) e.nextElement();
563:                            reply.setValue(hname, (String) h.getValue(hname));
564:                        }
565:                    }
566:                    reply.setStream(p.getInputStream());
567:                } catch (IOException ex) {
568:                    ex.printStackTrace();
569:                } catch (MimeParserException ex) {
570:                    // This script has generated invalid output:
571:                    String msg = (getURL(request) + ": emited invalid output ["
572:                            + ex.getMessage() + "]");
573:                    getServer().errlog(this , msg);
574:                    // Throw an HTTPException:
575:                    Reply error = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
576:                    error
577:                            .setContent("CGI error: unable to parse script headers.");
578:                    throw new HTTPException(error);
579:                }
580:                if (reply != null) {
581:                    reply.setDynamic(true);
582:                }
583:                return reply;
584:            }
585:
586:            /**
587:             * Add an enviornment binding to the given vector.
588:             * @param name The name of the enviornment variable.
589:             * @param val Its value.
590:             * @param into The vector to which accumulate bindings.
591:             */
592:
593:            private void addEnv(String name, String val, Vector into) {
594:                into.addElement(name + "=" + val);
595:            }
596:
597:            /**
598:             * Prepare the command to run for this CGI script, and run it.
599:             * @param request The request to handle.
600:             * @return The running CGI process object.
601:             * @exception ProtocolException If we weren't able 
602:             * to build the command or the environment.
603:             * @exception IOException if an IO erro occurs.
604:             */
605:
606:            protected Process makeCgiCommand(Request request)
607:                    throws ProtocolException, IOException {
608:                // Check the command attribute first:
609:                String query = null;
610:                String command[] = getCommand();
611:                if (command == null) {
612:                    Reply error = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
613:                    error
614:                            .setContent("CgiResource mis-configured: it doesn't have a "
615:                                    + " command attribute");
616:                    throw new HTTPException(error);
617:                }
618:                // Ok:
619:                Vector env = new Vector(32);
620:                httpd server = request.getClient().getServer();
621:                InetAddress sadr = server.getInetAddress();
622:                // Specified environment variables:
623:                // We do not handle the following variables:
624:                // - REMOTE_IDENT: would require usage of IDENT protocol.
625:                // Authentification type, if any:
626:                String svalue = (String) request
627:                        .getState(AuthFilter.STATE_AUTHTYPE);
628:                if (svalue != null)
629:                    addEnv("AUTH_TYPE", svalue, env);
630:                // Content length, if available:
631:                svalue = request.getValue("content-length");
632:                if (svalue != null)
633:                    addEnv("CONTENT_LENGTH", svalue, env);
634:                // Content type, if available:
635:                svalue = request.getValue("content-type");
636:                if (svalue != null)
637:                    addEnv("CONTENT_TYPE", svalue, env);
638:                // The gateway interface, hopefully 1.1 !
639:                addEnv("GATEWAY_INTERFACE", "CGI/1.1", env);
640:                // The PATH_INFO, which I am afraid I still don't understand:
641:                svalue = (String) request.getState(STATE_EXTRA_PATH);
642:                if (svalue == null)
643:                    addEnv("PATH_INFO", "/", env);
644:                else
645:                    addEnv("PATH_INFO", svalue, env);
646:                // The query string:
647:                query = request.getQueryString();
648:                if (query != null)
649:                    addEnv("QUERY_STRING", query, env);
650:                // The remote client IP address:
651:                svalue = request.getClient().getInetAddress().toString();
652:                addEnv("REMOTE_ADDR", svalue, env);
653:                // Authentified user:
654:                svalue = (String) request.getState(AuthFilter.STATE_AUTHUSER);
655:                if (svalue != null)
656:                    addEnv("REMOTE_USER", svalue, env);
657:                // Remote host name, if allowed:
658:                if (checkRemoteHost()) {
659:                    String host = request.getClient().getInetAddress()
660:                            .getHostName();
661:                    addEnv("REMOTE_HOST", host, env);
662:                }
663:                // The request method:
664:                addEnv("REQUEST_METHOD", request.getMethod(), env);
665:                // The script name :
666:                addEnv("SCRIPT_NAME", getURLPath(), env);
667:                // Server name:
668:                addEnv("SERVER_NAME", getServer().getHost(), env);
669:                // Server port:
670:                svalue = Integer.toString(getServer().getLocalPort());
671:                addEnv("SERVER_PORT", svalue, env);
672:                // Server protocol:
673:                addEnv("SERVER_PROTOCOL", request.getVersion(), env);
674:                // Server software:
675:                addEnv("SERVER_SOFTWARE", server.getSoftware(), env);
676:                if (getFileResource() != null) {
677:                    addEnv("PATH_TRANSLATED", getFileResource().getFile()
678:                            .getAbsolutePath(), env);
679:                }
680:
681:                //Add user env
682:                ArrayDictionary uenv = getUserEnv();
683:                if (uenv != null) {
684:                    Enumeration names = uenv.keys();
685:                    while (names.hasMoreElements()) {
686:                        String var = (String) names.nextElement();
687:                        addEnv(var, (String) uenv.get(var), env);
688:                    }
689:                }
690:                // All other request fields, yeah, let's lose even more time:
691:                Enumeration e = request.enumerateHeaderDescriptions(false);
692:                while (e.hasMoreElements()) {
693:                    HeaderDescription d = (HeaderDescription) e.nextElement();
694:                    addEnv(getEnvName(d.getName()), request.getHeaderValue(d)
695:                            .toString(), env);
696:                }
697:                // Command line:
698:                if (query != null) {
699:                    String querycmd[] = new String[command.length + 1];
700:                    System.arraycopy(command, 0, querycmd, 0, command.length);
701:                    querycmd[command.length] = query;
702:                    command = querycmd;
703:                }
704:                String aenv[] = new String[env.size()];
705:                env.copyInto(aenv);
706:                // Run the process:
707:                if (getInterpreter() != null) {
708:                    String run[] = new String[command.length + 1];
709:                    run[0] = getInterpreter();
710:                    System.arraycopy(command, 0, run, 1, command.length);
711:                    return Runtime.getRuntime().exec(run, aenv);
712:                } else {
713:                    return Runtime.getRuntime().exec(command, aenv);
714:                }
715:            }
716:
717:            /**
718:             * Lookup sub-resources.
719:             * Accumulate the remaning path in some special state of the request.
720:             * <p>This allows us to implement the <code>PATH_INFO</code> 
721:             * CGI variable properly.
722:             * @param ls Current lookup state.
723:             * @param lr Lookup result under construction.
724:             * @return A boolean <strong>true</strong> if lookup should continue,
725:             * <strong>false</strong> otherwise.
726:             * @exception ProtocolException (fixme doc)
727:             */
728:
729:            public boolean lookup(LookupState ls, LookupResult lr)
730:                    throws ProtocolException {
731:                // Get the extra path information:
732:                String extraPath = ls.getRemainingPath(true);
733:                if ((extraPath == null) || extraPath.equals(""))
734:                    extraPath = "/";
735:                // Keep this path info into the request, if possible:
736:                Request request = (Request) ls.getRequest();
737:                if (request != null)
738:                    request.setState(STATE_EXTRA_PATH, extraPath);
739:                lr.setTarget(getResource().getResourceReference());
740:                return super .lookup(ls, lr);
741:            }
742:
743:            /** 
744:             * GET method implementation.
745:             * this method is splitted into two cases:
746:             * <p>If the resource is able to generates its form, than run the script
747:             * to emit the form. Otherwsie, use our super class (FileResource) ability
748:             * to send the file that contains the form.
749:             * <p>Note that there is no need to feed the underlying process with
750:             * data in the GET case.
751:             * @param request The request to handle.
752:             * @exception ProtocolException If processing the request failed.
753:             * @exception ResourceException If the resource got a fatal error.
754:             */
755:            public Reply get(Request request) throws ProtocolException,
756:                    ResourceException {
757:                if (!checkGeneratesFormFlag())
758:                    return super .get(request);
759:                Process process = null;
760:                try {
761:                    process = makeCgiCommand(request);
762:                } catch (IOException e) {
763:                    e.printStackTrace();
764:                    Reply error = request.makeReply(HTTP.NOT_FOUND);
765:                    error.setContent("The resource's script wasn't found.");
766:                    throw new HTTPException(error);
767:                }
768:                return handleCGIOutput(process, request);
769:            }
770:
771:            /**
772:             * Handle the POST method according to CGI/1.1 specification.
773:             * The request body is sent back to the launched CGI script, as is, and
774:             * the script output is handled by the handleCGIOutput method.
775:             * @param request The request to process.
776:             * @exception ProtocolException If the processing failed.
777:             * @exception ResourceException If the resource got a fatal error.
778:             */
779:            public Reply post(Request request) throws ProtocolException,
780:                    ResourceException {
781:                Process process = null;
782:                // Launch the CGI process:
783:                try {
784:                    process = makeCgiCommand(request);
785:                } catch (IOException ex) {
786:                    // The process wasn't executable, emit a errlog message:
787:                    String msg = ("The process " + getCommand()[0]
788:                            + " couldn't be executed [" + ex.getMessage() + "]");
789:                    getServer().errlog(this , msg);
790:                    // Throw an internal server error:
791:                    Reply error = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
792:                    error.setContent("CGI script is misconfigured.");
793:                    throw new HTTPException(error);
794:                }
795:                // Now feed the process:
796:                try {
797:                    // Send the 100 status code:
798:                    Client client = request.getClient();
799:                    if (client != null)
800:                        client.sendContinue();
801:                    InputStream in = request.getInputStream();
802:                    if (in == null) {
803:                        // There was no input to that CCI, close process stream
804:                        process.getOutputStream().close();
805:                    } else {
806:                        // Some input to feed the process with:
807:                        (new ProcessFeeder(process, in)).start();
808:                    }
809:                } catch (IOException ex) {
810:                    // This is most probably a bad request:
811:                    Reply error = request.makeReply(HTTP.BAD_REQUEST);
812:                    error.setContent("The request didn't have a valid input.");
813:                    throw new HTTPException(error);
814:                }
815:                return handleCGIOutput(process, request);
816:            }
817:
818:            /**
819:             * At register time, if no command, use a suitable default.
820:             * THis method will set the command to the identifier, if it is not
821:             * provided.
822:             * @param values Default attribute values.
823:             */
824:
825:            public void registerResource(FramedResource resource) {
826:                super .registerResource(resource);
827:                //if no command is specified look for a file resource attached
828:                //and get its File absolute path if available.
829:                if (getCommand() == null) {
830:                    if (getFileResource() != null) {
831:                        try {
832:                            if (getFileResource().getFile() != null) {
833:                                String cmd[] = new String[1];
834:                                cmd[0] = getFileResource().getFile()
835:                                        .getAbsolutePath();
836:                                setValue(ATTR_COMMAND, cmd);
837:                            }
838:                        } catch (InvalidParentException ex) {
839:                            //nothing to do
840:                            //probably an indexer operation
841:                        }
842:                    }
843:                }
844:            }
845:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.