1 package com.ibm.staf.service.http;
2
3 /*****************************************************************************/
4 /* Software Testing Automation Framework (STAF) */
5 /* (C) Copyright IBM Corp. 2004 */
6 /* */
7 /* This software is licensed under the Eclipse Public License (EPL) V1.0. */
8 /*****************************************************************************/
9
10 /*****************************************************************************/
11 /* */
12 /* Class: WebSession */
13 /* Description: This class provides the handle to maintain a http session. */
14 /* */
15 /*****************************************************************************/
16
17 import com.ibm.staf.*;
18 import java.util.Vector;
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.Map;
22 import java.net.URL;
23 import java.net.MalformedURLException;
24 import java.io.IOException;
25 import java.io.FileNotFoundException;
26 import java.io.StringReader;
27 import java.io.File;
28 import java.io.InputStream;
29 import java.io.OutputStream;
30 import java.io.BufferedInputStream;
31 import java.io.FileInputStream;
32 import java.io.FileOutputStream;
33 import java.io.DataInputStream;
34 import java.io.DataOutputStream;
35 import java.io.FileWriter;
36
37 import org.w3c.dom.Document;
38
39 import com.ibm.staf.service.STAFServiceInterfaceLevel30;
40 import com.ibm.staf.STAFUtil;
41 import com.ibm.staf.service.http.html.InvalidParameterValueException;
42 import com.ibm.staf.service.http.html.WebLink;
43 import com.ibm.staf.service.http.html.WebForm;
44 import com.ibm.staf.service.http.html.HTMLParser;
45
46 // HTTP Client
47 import org.apache.commons.httpclient.*;
48 import org.apache.commons.httpclient.util.EncodingUtil;
49 import org.apache.commons.httpclient.methods.*;
50 import org.apache.commons.httpclient.params.HttpMethodParams;
51 import org.apache.commons.httpclient.auth.AuthScope;
52 import org.apache.commons.httpclient.methods.multipart.*;
53
54 // nekoHTML
55 import org.cyberneko.html.parsers.DOMParser;
56 import org.w3c.dom.html.HTMLDocument;
57
58 // xerces
59 import org.xml.sax.SAXException;
60 import org.xml.sax.InputSource;
61
62 public class WebSession
63 {
64 // These constants define the type of identification of the page element to
65 // be accessed.
66 public static final int NAME_ID_TYPE = 0;
67 public static final int ID_ID_TYPE = 1;
68 public static final int INDEX_ID_TYPE = 2;
69
70 // These constants define the parts of the summary
71 public static final String ID = "ID";
72 public static final String URL = "URL";
73 public static final String TITLE = "TITLE";
74 public static final String POLICY = "POLICY";
75 public static final String OWNER_INSTANCE_UUID = "OWNER_INSTANCE_UUID";
76 public static final String OWNER_MACHINE = "OWNER_MACHINE";
77 public static final String OWNER_HANDLE_NAME = "OWNER_HANDLE_NAME";
78 public static final String OWNER_HANDLE = "OWNER_HANDLE";
79 public static final String PARSE_CONTENT = "PARSE_CONTENT";
80 public static final String HTTP_PROXY_HOST = "HTTP_PROXY_HOST";
81 public static final String HTTP_PROXY_PORT = "HTTP_PROXY_PORT";
82
83 // These constants are used to define the hash map of required components
84 // of a requestMethod call
85 public static final String REQUEST_PARAMETERS = "PARAMETERS";
86 public static final String REQUEST_FILES = "FILES";
87 public static final String REQUEST_HEADERS = "HEADERS";
88 public static final String REQUEST_METHOD = "METHOD";
89 public static final String REQUEST_URL = "URL";
90 public static final String REQUEST_CONTENT = "CONTENT";
91 public static final String REQUEST_REDIRECT = "AUTO REDIRECT";
92
93 public static final String RETURN_STATUS_CODE = "RETURN STATUS CODE";
94 public static final String RETURN_STATUS_MESSAGE = "RETURN STATUS MSG";
95 public static final String RETURN_HEADERS = "RETURN HEADERS";
96
97 // These constants define the valid values for PARSECONTENT option
98 public static final String ENABLED = "Enabled";
99 public static final String DISABLED = "Disabled";
100 public static final String AUTODETECT = "AutoDetect";
101
102 protected int id;
103 protected String ownerInstanceUUID;
104 protected String ownerMachine;
105 protected String ownerHandleName;
106 protected int ownerHandle;
107 protected HTTP httpService;
108 protected HttpClient session;
109 protected HttpMethodBase lastRequest;
110 protected HTMLParser parser;
111 protected HashMap defaultHeaders;
112 protected HashMap authenticationSets;
113 protected boolean followRedirect;
114 protected String fParseContent;
115 protected String currentContents;
116 protected String currentContentsFileName;
117
118 // true means that a temporary session was opened for a single request
119 // (e.g. the SESSION option wasn't specified on the request)
120 protected boolean tempSession;
121
122 private static final int BUFF_SIZE = 4096;
123 private static final int MAX_STRING_SIZE = 51200;
124
125 /*****************************************************************************/
126 /* */
127 /* Method: Constructor */
128 /* Description: Constructor method */
129 /* Parameter: parentList - session list that this session is to be a part of */
130 /* it is required to determine the id of this session*/
131 /* info - request info */
132 /* */
133 /*****************************************************************************/
134
WebSession(SessionList parentList, STAFServiceInterfaceLevel30.RequestInfo info, HTTP httpService)135 public WebSession(SessionList parentList,
136 STAFServiceInterfaceLevel30.RequestInfo info,
137 HTTP httpService)
138 {
139 this(parentList, info, httpService, false);
140 }
141
WebSession(SessionList parentList, STAFServiceInterfaceLevel30.RequestInfo info, HTTP httpService, boolean tempSession)142 public WebSession(SessionList parentList,
143 STAFServiceInterfaceLevel30.RequestInfo info,
144 HTTP httpService, boolean tempSession)
145 {
146 this.ownerInstanceUUID = info.stafInstanceUUID;
147 this.ownerMachine = info.endpoint;
148 this.ownerHandleName = info.handleName;
149 this.ownerHandle = info.handle;
150 this.httpService = httpService;
151 this.tempSession = tempSession;
152 id = parentList.addSession(this);
153 session = new HttpClient();
154
155 lastRequest = null;
156 parser = new HTMLParser();
157 defaultHeaders = new HashMap();
158 authenticationSets = new HashMap();
159 followRedirect = false;
160 fParseContent = AUTODETECT;
161 currentContents = "";
162 currentContentsFileName = "";
163 }
164
releaseConnection()165 public void releaseConnection()
166 {
167 currentContents = "";
168
169 if (!currentContentsFileName.equals(""))
170 {
171 // Delete temporary file
172 (new File(currentContentsFileName)).delete();
173
174 currentContentsFileName = "";
175 }
176
177 if (lastRequest != null)
178 {
179 // Must call releaseConnection to release resources
180 lastRequest.releaseConnection();
181 lastRequest = null;
182 }
183
184 // Close any idle connections. This is required to close the socket
185 // so it doesn't remain open in a CLOSE_WAIT state.
186
187 session.getHttpConnectionManager().closeIdleConnections(0);
188
189 try
190 {
191 parser.setContent(HTMLParser.EMPTY_DOC);
192 }
193 catch (Exception e)
194 {
195 // HTMLParser.EMPTY_DOC is safe and will not cause an exception
196 }
197 }
198
199 /*****************************************************************************/
200 /* */
201 /* Method: getID */
202 /* Description: gets the session id of this WebSesson. */
203 /* Returns: the ID which identifies the session in the list */
204 /* */
205 /*****************************************************************************/
206
getID()207 public int getID()
208 {
209 return id;
210 }
211
212 /*****************************************************************************/
213 /* */
214 /* Method: getOwnerMachine */
215 /* Description: gets the owner machine for this WebSesson. */
216 /* Returns: the machine for the owner of this session */
217 /* */
218 /*****************************************************************************/
219
getOwnerMachine()220 public String getOwnerMachine()
221 {
222 return ownerMachine;
223 }
224
225 /*****************************************************************************/
226 /* */
227 /* Method: getOwnerHandleName */
228 /* Description: gets the owner handle name for this WebSesson. */
229 /* Returns: the handle name for the owner of this session */
230 /* */
231 /*****************************************************************************/
232
getOwnerHandleName()233 public String getOwnerHandleName()
234 {
235 return ownerHandleName;
236 }
237
238 /*****************************************************************************/
239 /* */
240 /* Method: getOwnerHandle */
241 /* Description: gets the owner handle for this WebSesson. */
242 /* Returns: the handle for the owner of this session */
243 /* */
244 /*****************************************************************************/
245
getOwnerHandle()246 public int getOwnerHandle()
247 {
248 return ownerHandle;
249 }
250
251 /*****************************************************************************/
252 /* */
253 /* Method: getCurrentContentsAsStream */
254 /* Description: get the contents returned by the last interaction */
255 /* Parameters: none */
256 /* Returns: the contents of the last interaction in an InputStream. */
257 /* This is the html code for the current page if the last action */
258 /* was a goto or link. Otherwise it is the message generated by */
259 /* the METHOD call. */
260 /* */
261 /*****************************************************************************/
262
getCurrentContentsAsStream()263 public InputStream getCurrentContentsAsStream() throws IOException
264 {
265 if (HTTP.DEBUG)
266 System.out.println("In WebSession.getResponseBodyAsStream()");
267
268 try
269 {
270 return lastRequest.getResponseBodyAsStream();
271 }
272 catch (NullPointerException e)
273 {
274 // No previous requests
275 }
276
277 // Return null if an error occurs
278 return null;
279 }
280
281 /*****************************************************************************/
282 /* */
283 /* Method: getCurrentContents */
284 /* Description: get the contents returned by the last interaction */
285 /* Parameters: none */
286 /* Returns: the contents of the last interaction in a String. */
287 /* This is the html code for the current page if the last action */
288 /* was a goto or link. Otherwise it is the message generated by the */
289 /* METHOD call. */
290 /* */
291 /*****************************************************************************/
292
getCurrentContents()293 public String getCurrentContents() throws STAFException,
294 ContentTooLargeException
295 {
296 if (HTTP.DEBUG)
297 System.out.println("In WebSession.getCurrentContents()");
298
299 // Get content from where setCurrentContent stored it.
300 // If content is small, the content is stored in a string.
301 // If content is large, the content is stored in a temporary file.
302
303 if (currentContentsFileName.equals(""))
304 {
305 // Current contents <= 50k are stored in a string
306
307 if (HTTP.DEBUG)
308 System.out.println("Current contents in string since < 50k");
309
310 return currentContents;
311 }
312 else
313 {
314 // Current contents > 50k are stored in a temporary file
315 // Read from the file specified by currentContentsFileName
316
317 if (HTTP.DEBUG)
318 System.out.println("Current contents in temp file " +
319 currentContentsFileName);
320
321 StringBuffer output = new StringBuffer();
322 InputStream instream = null;
323
324 final byte[] buffer = new byte[BUFF_SIZE];
325
326 try
327 {
328 instream = new DataInputStream(new FileInputStream(
329 currentContentsFileName));
330
331 // Read InputStream
332
333 while (true)
334 {
335 int amountRead = instream.read(buffer);
336
337 if (amountRead == -1)
338 {
339 break;
340 }
341
342 // Write to a string
343 output.append(new String(buffer, 0, amountRead));
344 }
345 }
346 catch(IOException e)
347 {
348 output = new StringBuffer(HTMLParser.EMPTY_DOC);
349
350 throw new STAFException(
351 STAFResult.FileReadError,
352 "Error getting current contents.\n" + e.toString());
353 }
354 catch(OutOfMemoryError e)
355 {
356 output = new StringBuffer();
357
358 throw new ContentTooLargeException(
359 "Getting the session content caused an OutOfMemoryError " +
360 "because it is too large. Recommend redirecting the content " +
361 "to a file using the FILE option or, if the content is not " +
362 "needed, you may be able to specify the RETURNNOCONTENT " +
363 "option depending on the request.");
364 }
365 finally
366 {
367 try
368 {
369 if (instream != null) instream.close();
370 }
371 catch(IOException e)
372 {
373 throw new STAFException(
374 STAFResult.FileReadError,
375 "Error getting current contents while closing " +
376 "stream.\n" + e.toString());
377 }
378 }
379
380 if (HTTP.DEBUG)
381 System.out.println("WebSession.getCurrentContents() return");
382
383 return output.toString();
384 }
385 }
386
387
388 /*****************************************************************************/
389 /* */
390 /* Method: setCurrentContents */
391 /* Description: Set the current contents for the last interaction by reading */
392 /* from the input stream. If temporary file (e.g. fileName == null)*/
393 /* and contents <= 50K, store the contents in a string. Otherwise, */
394 /* store the contents in a file. */
395 /* Also, set the content for the HTML parser if the contents for */
396 /* the last interaction is text/html. */
397 /* Parameters: instream - input stream containing the contents for the last */
398 /* interaction for this session. */
399 /* */
400 /*****************************************************************************/
setCurrentContents(InputStream instream, String fileName, String machine)401 public void setCurrentContents(InputStream instream,
402 String fileName, String machine)
403 throws STAFException, IOException
404 {
405 if (HTTP.DEBUG)
406 System.out.println("In WebSession.setCurrentContents()");
407
408 currentContents = "";
409 currentContentsFileName = "";
410
411 if (instream == null) return;
412
413 String localFileName = httpService.getTempDir() +
414 "session" + id + ".tmp";
415
416 // Write the result string as a stream of raw bytes (e.g.
417 // binary mode)
418
419 BufferedInputStream bis = null;
420 OutputStream outstream = null;
421 StringBuffer output = new StringBuffer();
422 long totalRead = 0;
423 final byte[] buffer = new byte[BUFF_SIZE];
424
425 // Read content from input stream and write content to a string if
426 // fileName is not specified (e.g. is null) or if the content stream
427 // size is small (e.g. <= MAX_STRING_SIZE). Otherwise, write the
428 // content to a file.
429
430 try
431 {
432 bis = new BufferedInputStream(instream);
433
434 outstream = new DataOutputStream(new FileOutputStream(
435 localFileName));
436
437 while (true)
438 {
439 int amountRead = bis.read(buffer);
440
441 if (amountRead == -1) break;
442
443 if ((fileName == null) && (totalRead <= MAX_STRING_SIZE))
444 {
445 // Write to a string
446 output.append(new String(buffer, 0, amountRead));
447 }
448
449 // Write to a file
450 outstream.write(buffer, 0, amountRead);
451
452 totalRead += amountRead;
453 }
454
455 if (HTTP.DEBUG)
456 System.out.println("totalRead=" + totalRead);
457 }
458 catch(IOException e)
459 {
460 // Delete the temporary file before throwing the exception
461
462 if (outstream != null) outstream.close();
463 (new File(localFileName)).delete();
464
465 throw new STAFException(
466 STAFResult.FileWriteError,
467 "Error setting current contents.\n" + e.toString());
468 }
469 finally
470 {
471 try
472 {
473 if (bis != null) bis.close();
474 if (outstream != null) outstream.close();
475 }
476 catch(IOException e)
477 {
478 (new File(localFileName)).delete();
479
480 throw new STAFException(
481 STAFResult.FileWriteError,
482 "Error setting current contents (when closing " +
483 "streams).\n" + e.toString());
484 }
485 }
486
487 if ((fileName == null) && (totalRead <= MAX_STRING_SIZE))
488 {
489 // Contents stored in a string
490
491 if (HTTP.DEBUG)
492 System.out.println("Contents stored in string");
493
494 currentContents = output.toString();
495
496 // Make sure the local temporary file is deleted
497
498 (new File(localFileName)).delete();
499 }
500 else
501 {
502 // Contents stored in a file
503
504 if (HTTP.DEBUG)
505 System.out.println("Contents stored in file " + localFileName);
506
507 currentContentsFileName = localFileName;
508 output = new StringBuffer("");
509 }
510
511 // Determine if should parse the content as HTML or not
512
513 boolean parseContent = false;
514
515 if (tempSession)
516 {
517 // If temporary session, don't parse the content as HTML (since it
518 // is of no value since won't be able to access the parsed HTML
519 // content)
520
521 if (HTTP.DEBUG)
522 System.out.println(
523 "Don't parse HTML content since temporary session");
524
525 // Return since don't need to set content to EMPTY_DOC
526 return;
527 }
528
529 if (fParseContent.equals(AUTODETECT))
530 {
531 // Auto-detect whether should parse the content as HTML by checking
532 // if the "Content-Type" header set by the Web Server contains
533 // "text/html". If so, then parse the content as HTML.
534
535 Header contentTypeHeader = lastRequest.getResponseHeader(
536 "Content-Type");
537
538 if (contentTypeHeader != null)
539 {
540 String contentType = contentTypeHeader.getValue();
541
542 if (HTTP.DEBUG)
543 System.out.println(
544 "Autodetect whether to parse content based on " +
545 "content type. Content type: " + contentType);
546
547 if ((contentType != null) &&
548 (contentType.indexOf("text/html") >= 0))
549 parseContent = true;
550 }
551 }
552 else if (fParseContent.equals(ENABLED))
553 {
554 parseContent = true;
555 }
556
557 if (HTTP.DEBUG)
558 System.out.println("Parse HTML content: " + parseContent);
559
560 // If should parse the content as HTML, set the parser content to the
561 // current contents; otherwise, set the parser content to EMPTY_DOC
562
563 try
564 {
565 if (parseContent)
566 {
567 if (!currentContents.equals(""))
568 parser.setContent(currentContents);
569 else
570 parser.setContent(
571 new FileInputStream(currentContentsFileName));
572 }
573 else
574 {
575 parser.setContent(HTMLParser.EMPTY_DOC);
576 }
577 }
578 catch (Exception e)
579 {
580 try
581 {
582 parser.setContent(HTMLParser.EMPTY_DOC);
583 }
584 catch (Exception ex)
585 {
586 // Do nothing. EMPTY_DOC is error free
587 }
588 }
589 }
590
591 /*****************************************************************************/
592 /* */
593 /* Method: writeContentToFile */
594 /* Description: utility method to write the current content to a file */
595 /* Parameters: filename - string representation of a file */
596 /* machineName - name of the machine to write the file to */
597 /* Returns: void */
598 /* */
599 /*****************************************************************************/
600
writeContentToFile(String toFile, String toMachine)601 public void writeContentToFile(String toFile, String toMachine)
602 throws IOException, STAFException
603 {
604 if (HTTP.DEBUG)
605 System.out.println("WebSession.writeContentToFile()");
606
607 // Store name for file redirect
608 String fName = toFile;
609
610 if (currentContentsFileName.equals(""))
611 {
612 // Current contents reside in a string. Write contents to a file.
613
614 String fileName = toFile;
615
616 if (toMachine != null)
617 {
618 // Create a temporary file name to use to store the content in
619 fileName = httpService.getTempDir() + "file" +
620 httpService.getTempFileCount() + ".tmp";
621 }
622
623 File outFile = new File(fileName);
624 FileWriter out = new FileWriter(outFile);
625 out.write(currentContents);
626 out.close();
627
628 if (toMachine == null)
629 {
630 // The contents have already been written to the specified file
631 // on the local machine
632 return;
633 }
634
635 // Copy the temporary file on the local machine to the specified file
636 // on the specified machine.
637
638 String request = "COPY FILE " + fileName +
639 " TOFILE " + fName + " TOMACHINE " + toMachine;
640
641 if (HTTP.DEBUG)
642 System.out.println("STAF local FS " + request);
643
644 STAFResult res = httpService.getServiceHandle().submit2(
645 "local", "FS", request);
646
647 // Delete the temporary local file
648
649 (new File(fileName)).delete();
650
651 if (res.rc != 0)
652 {
653 String errMsg = "FS " + request + " failed with RC=" + res.rc +
654 " Result=" + res.result;
655 throw new STAFException(res.rc, errMsg);
656 }
657 }
658 else
659 {
660 // Current contents reside in a file on the local service machine
661
662 String request = "";
663
664 if (toMachine == null)
665 {
666 // Copy the contents file to a file on the local service machine
667 request = "COPY FILE " + currentContentsFileName +
668 " TOFILE " + fName;
669 }
670 else
671 {
672 // Copy the contents file to a file on the specified machine
673 request = "COPY FILE " + currentContentsFileName +
674 " TOFILE " + fName + " TOMACHINE " + toMachine;
675 }
676
677 if (HTTP.DEBUG)
678 System.out.println("STAF local FS " + request);
679
680 STAFResult res = httpService.getServiceHandle().submit2(
681 "local", "FS", request);
682
683 if (res.rc != 0)
684 {
685 String errMsg = "FS " + request + " failed with RC=" + res.rc +
686 " Result=" + res.result;
687 throw new STAFException(res.rc, errMsg);
688 }
689 }
690
691 return;
692 }
693
694 /*****************************************************************************/
695 /* */
696 /* Method: getCurrentTitle */
697 /* Description: get the title of the current page of the session. */
698 /* Parameters: none */
699 /* Returns: the title of the current page of the session. If there is no */
700 /* title, an empty string is returned. */
701 /* */
702 /*****************************************************************************/
703
getCurrentTitle()704 public String getCurrentTitle()
705 {
706 try
707 {
708 return parser.getTitle();
709 }
710 catch (Exception e)
711 {
712 // Ignore errors (like DOMExceptions, NullPointerException) when
713 // getting the title to so that a QUERY SESSION or LIST SESSIONS
714 // request won't fail just because could not get the title for a
715 // session.
716 return "";
717 }
718 }
719
720 /*****************************************************************************/
721 /* */
722 /* Method: getCurrentUrl */
723 /* Description: get the url of the current page of the session. */
724 /* Parameters: none */
725 /* Returns: the current url */
726 /* */
727 /*****************************************************************************/
728
getCurrentUrl()729 public String getCurrentUrl()
730 {
731 try{
732 String url = lastRequest.getURI().getURI();
733 return url;
734 }catch (NullPointerException e){
735 // no previous requests
736 }catch (URIException e){
737 }
738
739 return "";
740 }
741
742 /*****************************************************************************/
743 /* */
744 /* Method: getCurrentStatusCode */
745 /* Description: get the status code of the last request of the session. */
746 /* Parameters: none */
747 /* Returns: the current status code */
748 /* */
749 /*****************************************************************************/
750
getCurrentStatusCode()751 public int getCurrentStatusCode()
752 {
753 try{
754 return lastRequest.getStatusCode();
755 }catch (NullPointerException e){
756 // no previous requests
757 }
758 return -1;
759 }
760
761 /*****************************************************************************/
762 /* */
763 /* Method: getCurrentStatusText */
764 /* Description: get the status message of the last request of the session. */
765 /* Parameters: none */
766 /* Returns: the current status message */
767 /* */
768 /*****************************************************************************/
769
getCurrentStatusText()770 public String getCurrentStatusText()
771 {
772 try{
773 return lastRequest.getStatusText();
774 }catch (NullPointerException e){
775 // no previous requests
776 }
777 return "";
778 }
779
780 /*****************************************************************************/
781 /* */
782 /* Method: getCurrentStatus */
783 /* Description: get the status of the last request of the session. */
784 /* Parameters: none */
785 /* Returns: the current status */
786 /* */
787 /*****************************************************************************/
788
getCurrentStatus()789 public String getCurrentStatus()
790 {
791
792 int rc = getCurrentStatusCode();
793 String rm = getCurrentStatusText();
794 return rc + "\n" + rm;
795 }
796
797 /*****************************************************************************/
798 /* */
799 /* Method: getCookiePolicy */
800 /* Description: get the cookie handling policy for this session. */
801 /* Parameters: none */
802 /* Returns: the cookie handling policy */
803 /* */
804 /*****************************************************************************/
805
getCookiePolicy()806 public String getCookiePolicy()
807 {
808 return session.getParams().getCookiePolicy();
809 }
810
811 /*****************************************************************************/
812 /* */
813 /* Method: setCookiePolicy */
814 /* Description: set the cookie handling policy for this session. If an */
815 /* invalid policy is selected the DEFAULT policy is set. */
816 /* Valid types: NETSCAPE, RFC2109, BROWSER, IGNORE */
817 /* Default policy is RFC2109. */
818 /* Parameters: policy - the new cookie handling policy for the session. */
819 /* Returns: void */
820 /* */
821 /*****************************************************************************/
822
setCookiePolicy(String policy)823 public void setCookiePolicy(String policy)
824 {
825 CookieAccess.setCookiePolicy(policy, session);
826 }
827
828 /*****************************************************************************/
829 /* */
830 /* Method: getCookieNames */
831 /* Description: get a list of cookies associated with this session. */
832 /* Parameters: none */
833 /* Returns: a list of cookies associated with this session */
834 /* */
835 /*****************************************************************************/
836
getCookieNames()837 public Vector getCookieNames()
838 {
839 return CookieAccess.getCookieNames(session);
840 }
841
842 /*****************************************************************************/
843 /* */
844 /* Method: getCookieValue */
845 /* Description: get the value of the cookie with the specified name. */
846 /* This may need to change to get cookie summary to obtain */
847 /* domain and path information about a specific cookie. */
848 /* Parameters: name - the name of the cookie */
849 /* Returns: the value of the specified cookie. */
850 /* */
851 /*****************************************************************************/
852
getCookieValue(String name)853 public String getCookieValue(String name) throws InvalidCookieIDException
854 {
855 return CookieAccess.getCookieValue(name, session);
856 }
857
858 /*****************************************************************************/
859 /* */
860 /* Method: setCookieValue */
861 /* Description: sets the value of the specifed cookie to the specified value */
862 /* Parameters: name - name of the cookie */
863 /* value - new value for the cookie */
864 /* Returns: void */
865 /* Throws: InvalidCookieIDException if the cookie does not exist */
866 /* */
867 /*****************************************************************************/
868
setCookieValue(String name, String value)869 public void setCookieValue (String name, String value)
870 throws InvalidCookieIDException
871 {
872 CookieAccess.setCookieValue(name, value, session);
873
874 }
875
876 /*****************************************************************************/
877 /* */
878 /* Method: addCookie */
879 /* Description: Add a new cookie to the session. This may need more */
880 /* parameters if path and domain are to be specified. */
881 /* Parameters: name - name of the cookie */
882 /* value - new value for the cookie */
883 /* Returns: void */
884 /* */
885 /*****************************************************************************/
886
addCookie(String name, String value)887 public void addCookie(String name, String value)
888 {
889 CookieAccess.addCookie(CookieAccess.createCookie(name,value), session);
890 }
891
892 /*****************************************************************************/
893 /* */
894 /* Method: deleteCookie */
895 /* Description: Delete the specified cookie from the session. If the cookie */
896 /* does not exist, no error is declared. */
897 /* Parameters: name - name of the cookie */
898 /* Returns: void */
899 /* */
900 /*****************************************************************************/
901
deleteCookie(String name)902 public void deleteCookie(String name) throws InvalidCookieIDException
903 {
904 CookieAccess.deleteCookie(name, session);
905 }
906
907 /*****************************************************************************/
908 /* */
909 /* Method: summarizeCookie */
910 /* Description: Get the information about a cookie. If the cookie is not in */
911 /* the session throw an InvalidElementException. */
912 /* Parameters: name - name of the cookie */
913 /* Returns: description of the cookie */
914 /* */
915 /*****************************************************************************/
916
summarizeCookie(String name)917 public HashMap summarizeCookie(String name) throws
918 InvalidCookieIDException
919 {
920 return CookieAccess.getCookieSummary(name, session);
921 }
922
923 /*****************************************************************************/
924 /* */
925 /* Method: listCookies */
926 /* Description: return a summary of all cookies in the current page */
927 /* Parameters: None */
928 /* Returns: the summary of all cookies in the current page */
929 /* */
930 /*****************************************************************************/
listCookies()931 public HashMap[] listCookies()
932 {
933 return CookieAccess.listCookies(session);
934 }
935
936 /*****************************************************************************/
937 /* */
938 /* Method: findLink */
939 /* Description: Find the specified link in the current page. If the link is */
940 /* not in the page or an invalid id type or an invalid value */
941 /* was specified throw an InvalidElementException. */
942 /* Parameters: linkID - the identified for the link */
943 /* idType - the type of id used to identify the link */
944 /* ID_ID_TYPE and NAME_ID_TYPE are accepted */
945 /* Returns: the link */
946 /* */
947 /*****************************************************************************/
948
findLink(String linkID, int idType)949 protected WebLink findLink(String linkID, int idType)
950 throws InvalidElementIDException
951 {
952 if (idType == ID_ID_TYPE)
953 return parser.getLinkByID(linkID);
954
955 if (idType == NAME_ID_TYPE)
956 return parser.getLinkByName(linkID);
957
958 if (idType == INDEX_ID_TYPE)
959 {
960 // Make sure specified index is numeric
961 try
962 {
963 int index = (new Integer(linkID)).intValue();
964 }catch (NumberFormatException e)
965 {
966 throw new InvalidElementIDException(
967 linkID, "LINK INDEX " + linkID + " is not an integer");
968 }
969
970 return parser.getLinkByIndex(Integer.parseInt(linkID));
971 }
972
973 throw new InvalidElementIDException(linkID, "Bad ID Type.");
974 }
975
976 /*****************************************************************************/
977 /* */
978 /* Method: summarizeLink */
979 /* Description: Get the information about a link. If the link is not in the */
980 /* page or an invalid id type was specified throw an */
981 /* InvalidElementException. */
982 /* Parameters: linkID - the identified for the link */
983 /* idType - the type of id used to identify the link */
984 /* ID_ID_TYPE and NAME_ID_TYPE are accepted */
985 /* Returns: description of the link. */
986 /* */
987 /*****************************************************************************/
988
summarizeLink(String linkID, int idType)989 public HashMap summarizeLink(String linkID, int idType) throws
990 InvalidElementIDException
991 {
992 WebLink link = findLink(linkID, idType);
993
994 try
995 {
996 return link.getSummary();
997
998 }catch (NullPointerException e)
999 {
1000 throw new InvalidElementIDException (linkID, "Link " + linkID);
1001 }
1002 }
1003
1004 /*****************************************************************************/
1005 /* */
1006 /* Method: listLinks */
1007 /* Description: return a summary of all links in the current page */
1008 /* Parameters: None */
1009 /* Returns: the summary of all links in the current page */
1010 /* */
1011 /*****************************************************************************/
listLinks()1012 public HashMap[] listLinks()
1013 {
1014 return parser.listLinks();
1015 }
1016
1017 /*****************************************************************************/
1018 /* */
1019 /* Method: followLink */
1020 /* Description: Send the session to the target of the specified link in the */
1021 /* current page. If the link is not in the page or an invalid */
1022 /* id type was specified throw an InvalidElementException. */
1023 /* Parameters: linkID - the identified for the link */
1024 /* idType - the type of id used to identify the link */
1025 /* ID_ID_TYPE and NAME_ID_TYPE are accepted */
1026 /* Returns: void */
1027 /* */
1028 /*****************************************************************************/
1029
followLink(String linkID, int idType, Boolean redirect)1030 public void followLink(String linkID, int idType, Boolean redirect) throws
1031 InvalidElementIDException, MalformedURLException, IOException,
1032 STAFException
1033 {
1034 WebLink link = findLink(linkID, idType);
1035
1036 try
1037 {
1038 HashMap request = link.getRequest();
1039 request.put(REQUEST_REDIRECT, redirect);
1040
1041 requestMethod(request);
1042
1043 }catch (NullPointerException e)
1044 {
1045 throw new InvalidElementIDException (linkID, "Link " + linkID);
1046 }
1047 }
1048
1049 /*****************************************************************************/
1050 /* */
1051 /* Method: findForm */
1052 /* Description: Find the specified form in the current page. If the form is */
1053 /* not in the page or an invalid id type was specified throw an */
1054 /* InvalidElementException. */
1055 /* Parameters: formID - the identified for the form */
1056 /* idType - the type of id used to identify the form */
1057 /* ID_ID_TYPE INDEX_ID_TYPE and NAME_ID_TYPE are */
1058 /* accepted */
1059 /* Returns: the form */
1060 /* */
1061 /*****************************************************************************/
1062
findForm(String formID, int idType)1063 protected WebForm findForm(String formID, int idType)
1064 throws InvalidElementIDException
1065 {
1066 if (idType == NAME_ID_TYPE)
1067 return parser.getFormByName(formID);
1068
1069 if (idType == ID_ID_TYPE)
1070 return parser.getFormByID(formID);
1071
1072 if (idType == INDEX_ID_TYPE)
1073 {
1074 // Make sure specified index is numeric
1075 try
1076 {
1077 int index = (new Integer(formID)).intValue();
1078 }catch (NumberFormatException e)
1079 {
1080 throw new InvalidElementIDException(
1081 formID, "FORM INDEX " + formID + " is not an integer");
1082 }
1083
1084 return parser.getFormByIndex(Integer.parseInt(formID));
1085 }
1086
1087 throw new InvalidElementIDException(formID, "Bad ID Type.");
1088 }
1089
1090 /*****************************************************************************/
1091 /* */
1092 /* Method: getFormControlIDs */
1093 /* Description: Get the control ids in the specified form in the current */
1094 /* page. If the form is not in the page or an invalid id type */
1095 /* was specified throw an InvalidElementException. */
1096 /* Parameters: formID - the identified for the form */
1097 /* idType - the type of id used to identify the form */
1098 /* ID_ID_TYPE INDEX_ID_TYPE and NAME_ID_TYPE are */
1099 /* accepted */
1100 /* Returns: a list of control ID's */
1101 /* */
1102 /*****************************************************************************/
1103
getFormControlIDs(String formID, int idType)1104 public String[] getFormControlIDs(String formID, int idType)
1105 throws InvalidElementIDException
1106 {
1107 WebForm form = findForm(formID, idType);
1108 return form.getParameterKeyList();
1109 }
1110
1111 /*****************************************************************************/
1112 /* */
1113 /* Method: setFormElement */
1114 /* Description: Set the value of the specified control in the specified form */
1115 /* in the current page. If the form is not in the page or an */
1116 /* invalid id type was specified or an invalid control name was */
1117 /* specified throw an InvalidElementException. */
1118 /* Parameters: formID - the identified for the form */
1119 /* idType - the type of id used to identify the form */
1120 /* ID_ID_TYPE INDEX_ID_TYPE and NAME_ID_TYPE are */
1121 /* accepted */
1122 /* elementID - the id of the control */
1123 /* value - the value ot assign to the control */
1124 /* Returns: void */
1125 /* */
1126 /*****************************************************************************/
1127
setFormElement(String formID, int idType, String elementID, String value)1128 public void setFormElement(String formID, int idType, String elementID,
1129 String value) throws InvalidElementIDException,
1130 InvalidParameterValueException
1131 {
1132 WebForm form = findForm(formID, idType);
1133
1134 try
1135 {
1136 form.setParameterValue(elementID, value);
1137
1138 }catch (NullPointerException e)
1139 {
1140 throw new InvalidElementIDException (formID, "Form " + formID);
1141 }
1142 }
1143
1144 /*****************************************************************************/
1145 /* */
1146 /* Method: summarizeForm */
1147 /* Description: Get the information about a form. If the form is not in the */
1148 /* page or an invalid id type was specified throw an */
1149 /* InvalidElementException. */
1150 /* Parameters: formID - the identified for the form */
1151 /* idType - the type of id used to identify the form */
1152 /* ID_ID_TYPE INDEX_ID_TYPE and NAME_ID_TYPE are */
1153 /* accepted */
1154 /* Returns: description of the form. */
1155 /* */
1156 /*****************************************************************************/
1157
summarizeForm(String formID, int idType)1158 public HashMap summarizeForm(String formID, int idType) throws
1159 InvalidElementIDException
1160 {
1161 WebForm form = findForm (formID, idType);
1162
1163 try
1164 {
1165 return form.getSummary();
1166
1167 }catch (NullPointerException e)
1168 {
1169 throw new InvalidElementIDException (formID, "Form " + formID);
1170 }
1171 }
1172
1173 /*****************************************************************************/
1174 /* */
1175 /* Method: summarizeFormElement */
1176 /* Description: Get the information about a form control. If the form is not*/
1177 /* in the page or an invalid id type was specified throw an */
1178 /* InvalidElementException. */
1179 /* Parameters: formID - the identified for the form */
1180 /* idType - the type of id used to identify the form */
1181 /* ID_ID_TYPE INDEX_ID_TYPE and NAME_ID_TYPE are */
1182 /* accepted */
1183 /* formControlKey - the key used to identify the form contorl */
1184 /* Returns: description of the form. */
1185 /* */
1186 /*****************************************************************************/
1187
summarizeFormControl(String formID, int idType, String formControlKey)1188 public HashMap summarizeFormControl(String formID, int idType,
1189 String formControlKey) throws
1190 InvalidElementIDException
1191 {
1192 WebForm form = findForm (formID, idType);
1193
1194 try
1195 {
1196 return form.getParameterSummary(formControlKey);
1197
1198 }catch (NullPointerException e)
1199 {
1200 throw new InvalidElementIDException (formID, "Form " + formID);
1201 }
1202 }
1203 /*****************************************************************************/
1204 /* */
1205 /* Method: listForms */
1206 /* Description: return a summary of all forms in the current page */
1207 /* Parameters: None */
1208 /* Returns: the summary of all forms in the current page */
1209 /* */
1210 /*****************************************************************************/
listForms()1211 public HashMap[] listForms()
1212 {
1213 return parser.listForms();
1214 }
1215
1216 /*****************************************************************************/
1217 /* */
1218 /* Method: getFormElement */
1219 /* Description: Get the value of the specified control in the specified form */
1220 /* in the current page. If the form is not in the page or an */
1221 /* invalid id type was specified or an invalid control name was */
1222 /* specified throw an InvalidElementException. */
1223 /* Parameters: formID - the identified for the form */
1224 /* idType - the type of id used to identify the form */
1225 /* ID_ID_TYPE INDEX_ID_TYPE and NAME_ID_TYPE are */
1226 /* accepted */
1227 /* elementID - the id of the control */
1228 /* Returns: the value of the specified control */
1229 /* */
1230 /*****************************************************************************/
1231
getFormElement(String formID, int idType, String elementID)1232 public String getFormElement(String formID, int idType, String elementID)
1233 throws InvalidElementIDException
1234 {
1235 String value = null;
1236
1237 WebForm form = findForm(formID, idType);
1238
1239 try
1240 {
1241 value = form.getParameterValue(elementID);
1242
1243 }catch (NullPointerException e)
1244 {
1245 throw new InvalidElementIDException (formID, "Form " + formID);
1246 }
1247
1248 return value;
1249 }
1250
1251 /*****************************************************************************/
1252 /* */
1253 /* Method: submitForm */
1254 /* Description: Submit the specified form in the current page. If the form */
1255 /* is not in the page or an invalid id type was specified */
1256 /* specified throw an InvalidElementException. */
1257 /* Parameters: formID - the identified for the form */
1258 /* idType - the type of id used to identify the form */
1259 /* ID_ID_TYPE INDEX_ID_TYPE and NAME_ID_TYPE are */
1260 /* accepted */
1261 /* Returns: void */
1262 /* */
1263 /*****************************************************************************/
1264
submitForm(String formID, int idType, Boolean redirect)1265 public void submitForm(String formID, int idType, Boolean redirect) throws
1266 MalformedURLException, IOException, FileNotFoundException,
1267 InvalidElementIDException, STAFException
1268 {
1269 WebForm form = findForm(formID, idType);
1270
1271 try
1272 {
1273 HashMap request = form.getRequest();
1274 request.put(REQUEST_REDIRECT, redirect);
1275
1276 requestMethod(request);
1277
1278 }catch (NullPointerException e)
1279 {
1280 throw new InvalidElementIDException (formID, "Form " + formID);
1281 }
1282 }
1283
1284 /*****************************************************************************/
1285 /* */
1286 /* Method: resetForm */
1287 /* Description: Reset the specified form in the current page. If the form */
1288 /* is not in the page or an invalid id type was specified */
1289 /* specified throw an InvalidElementException. */
1290 /* Parameters: formID - the identified for the form */
1291 /* idType - the type of id used to identify the form */
1292 /* ID_ID_TYPE INDEX_ID_TYPE and NAME_ID_TYPE are */
1293 /* accepted */
1294 /* Returns: void */
1295 /* */
1296 /*****************************************************************************/
1297
resetForm(String formID, int idType)1298 public void resetForm(String formID, int idType)
1299 throws InvalidElementIDException
1300 {
1301 WebForm form = findForm(formID, idType);
1302
1303 try
1304 {
1305 form.reset();
1306
1307 }catch (NullPointerException e)
1308 {
1309 throw new InvalidElementIDException (formID, "Form " + formID);
1310 }
1311 }
1312
1313 /*****************************************************************************/
1314 /* */
1315 /* Method: setRequestHeader */
1316 /* Description: Set the request to include the header specified. If the */
1317 /* header is already part of the request it is replaced by the */
1318 /* new value. If it is not present it is added. */
1319 /* Parameters: request - this is the request for the header */
1320 /* header - this is the header to be set */
1321 /* Returns: void */
1322 /* */
1323 /*****************************************************************************/
1324
setRequestHeader(HttpMethodBase request, Header header)1325 protected void setRequestHeader(HttpMethodBase request,
1326 Header header)
1327 {
1328 // this is a case insensitive match
1329 Header h = request.getRequestHeader(header.getName());
1330
1331 if (h == null)
1332 request.addRequestHeader(header);
1333 else
1334 request.setRequestHeader(header);
1335 }
1336
1337 /*****************************************************************************/
1338 /* */
1339 /* Method: requestMethod */
1340 /* Description: submit the http request described */
1341 /* Parameters: data - hash map containing the components of the request */
1342 /* Returns: void */
1343 /* */
1344 /*****************************************************************************/
1345
requestMethod(HashMap data)1346 public void requestMethod(HashMap data)throws MalformedURLException,
1347 IOException, FileNotFoundException, STAFException
1348
1349 {
1350 requestMethod((String)data.get(REQUEST_URL),
1351 (String)data.get(REQUEST_METHOD),
1352 (HashMap)data.get(REQUEST_HEADERS),
1353 (Vector)data.get(REQUEST_PARAMETERS),
1354 (Vector)data.get(REQUEST_FILES),
1355 (String)data.get(REQUEST_CONTENT),
1356 (Boolean)data.get(REQUEST_REDIRECT),
1357 null, null, false);
1358 }
1359
1360 /*****************************************************************************/
1361 /* */
1362 /* Method: requestMethod */
1363 /* Description: submit the http request described */
1364 /* Parameters: targetURL - the target url for this request */
1365 /* method - the method of the http request */
1366 /* headers - the headers to submit with the http request */
1367 /* params - the parameters to submit with the http request */
1368 /* files - a list of file names and associed parameter names to */
1369 /* submit with the http request */
1370 /* content - the body of the http request if no files or */
1371 /* parameters were specified */
1372 /* redirect - indicates whether to follow redirects */
1373 /* toFile - specifies the fully-qualified name of a file where */
1374 /* the response should be stored (or null if not */
1375 /* specified) */
1376 /* toMachine - specifies the machine that should be used to */
1377 /* store the toFile (or null if not specified) */
1378 /* urlEncoded - specifies whether the targetURL is already */
1379 /* escape-encoded (aka percent-encoded) */
1380 /* Returns: void */
1381 /* */
1382 /*****************************************************************************/
1383
requestMethod(String targetURL, String method, HashMap headers, Vector params, Vector files, String content, Boolean redirect, String toFile, String toMachine, boolean urlEncoded)1384 public void requestMethod(String targetURL, String method,
1385 HashMap headers, Vector params,
1386 Vector files, String content,
1387 Boolean redirect,
1388 String toFile, String toMachine,
1389 boolean urlEncoded)
1390 throws MalformedURLException, IOException, FileNotFoundException,
1391 STAFException
1392 {
1393 // clean up the url and make it absolute
1394 targetURL = resolveUrl(targetURL, urlEncoded);
1395
1396 // check to see if pre-emptive authentication is possible.
1397 session.getParams().setAuthenticationPreemptive(false);
1398 // strip off the protocol
1399 String host = targetURL.substring(targetURL.indexOf("://") + 3);
1400
1401 Iterator it = authenticationSets.keySet().iterator();
1402
1403 // match the current host with one in the list of automatic authenticators
1404 // if it exists
1405 while(it.hasNext())
1406 {
1407 String key = (String) it.next();
1408 if (host.startsWith(key))
1409 try
1410 {
1411 session.getParams().setAuthenticationPreemptive(true);
1412 String [] values = getAuthenticationSetValues(key);
1413 Credentials creds = new NTCredentials
1414 (values[0], values[1], key, values[2]);
1415
1416 //session.getState().setCredentials(null, key, creds);
1417 session.getState().setCredentials(new AuthScope(
1418 key, AuthScope.ANY_PORT, AuthScope.ANY_REALM), creds);
1419 }
1420 catch (InvalidElementIDException e)
1421 {
1422 /* do nothing this won't be thrown since key is gotten from a list of
1423 existing keys */
1424 }
1425 }
1426
1427 releaseConnection();
1428
1429 // purge expired cookies
1430 java.util.Date now = new java.util.Date();
1431 CookieAccess.purgeExpiredCookies(now, session);
1432
1433 // create request
1434 try{
1435 if (method.equalsIgnoreCase("GET"))
1436 {
1437 lastRequest = new GetMethod (targetURL);
1438 // allow for parameters
1439 if (content == null)
1440 content = "";
1441 content = "?" + content;
1442 }
1443 else if (method.equalsIgnoreCase("HEAD"))
1444 lastRequest = new HeadMethod (targetURL);
1445 else if (method.equalsIgnoreCase("TRACE"))
1446 lastRequest = new TraceMethod (targetURL);
1447 else if (method.equalsIgnoreCase("OPTIONS"))
1448 lastRequest = new OptionsMethod (targetURL);
1449 else if (method.equalsIgnoreCase("DELETE"))
1450 lastRequest = new DeleteMethod (targetURL);
1451 else if (method.equalsIgnoreCase("PUT"))
1452 lastRequest = new PutMethod (targetURL);
1453 else if (method.equalsIgnoreCase("POST"))
1454 lastRequest = new PostMethod (targetURL);
1455 }catch (java.lang.IllegalArgumentException e)
1456 {
1457 // - when URI is invalid
1458 throw new MalformedURLException("Invalid URI " + targetURL);
1459 }
1460 catch(java.lang.IllegalStateException e)
1461 {
1462 //- when protocol of the absolute URI is not recognised
1463 throw new MalformedURLException("Invalid protocol " + targetURL);
1464 }
1465
1466 if (lastRequest == null)
1467 throw new MalformedURLException("Bad Method");
1468
1469 // set default headers
1470 it = defaultHeaders.keySet().iterator();
1471 while(it.hasNext())
1472 {
1473 String key = (String) it.next();
1474 String value = (String) defaultHeaders.get(key);
1475 setRequestHeader(lastRequest, new Header(key, value));
1476 }
1477
1478 // set requested headers
1479 if (headers != null)
1480 {
1481 it = headers.keySet().iterator();
1482
1483 while(it.hasNext())
1484 {
1485 String key = (String) it.next();
1486 String value = (String) headers.get(key);
1487 setRequestHeader(lastRequest, new Header(key, value));
1488 }
1489 }
1490
1491 // Add parameters
1492
1493 NameValuePair[] pairs = null;
1494
1495 if (params != null)
1496 {
1497 int numParams = params.size();
1498 pairs = new NameValuePair[numParams];
1499
1500 for (int i = 0; i < numParams; i++)
1501 {
1502 Vector pair = (Vector)params.elementAt(i);
1503 String key = (String)pair.elementAt(0);
1504 String value = STAFUtil.removePrivacyDelimiters(
1505 (String)pair.elementAt(1));
1506
1507 if (PostMethod.class == lastRequest.getClass())
1508 {
1509 ((PostMethod)lastRequest).addParameter(key, value);
1510 }
1511 else
1512 {
1513 // Need to url encode key and value
1514 pairs[i] = new NameValuePair (key, value);
1515 }
1516 }
1517 }
1518
1519 // Add files, parameters, or content
1520
1521 try
1522 {
1523 if (files != null)
1524 {
1525 // This indicates a Multipart POST method
1526
1527 // The Multipart POST method uses a different request body
1528 // format (e.g. MultipartRequestEntity) than a POST method.
1529
1530 int numFiles = files.size();
1531 Part[] parts = new Part[numFiles];
1532
1533 // Add files to parts array
1534
1535 for (int i = 0; i < numFiles; i++)
1536 {
1537 Vector pair = (Vector)files.elementAt(i);
1538 String key = (String)pair.elementAt(0);
1539 String value = (String)pair.elementAt(1);
1540
1541 // Note: The key is not currently used.
1542 // I think Blake used a key in case support for
1543 // CONTENTFILEMACHINE was added in the future so that the
1544 // key could be used to match a CONTENTFILE option to a
1545 // CONTENTFILEMACHINE option.
1546
1547 try
1548 {
1549 parts[i] = new FilePart(value, new File(value));
1550 }
1551 catch (FileNotFoundException e)
1552 {
1553 // Error in getting file to be added to a post
1554
1555 String errMsg = " specified for INPUT FILE form " +
1556 "control:\n";
1557
1558 if (value.equals(""))
1559 errMsg = "No value" + errMsg;
1560 else
1561 errMsg = "Invalid value" + errMsg;
1562
1563 throw new FileNotFoundException(
1564 errMsg + " <INPUT type=\"file\" name=\"" + key +
1565 "\" value=\"" + value + "\" ...>" +
1566 "\nFileNotFoundException message: " +
1567 e.getMessage());
1568 }
1569 }
1570
1571 ((PostMethod)lastRequest).setRequestEntity(
1572 new MultipartRequestEntity(parts, lastRequest.getParams()));
1573 }
1574 else if ((params != null) &&
1575 (GetMethod.class == lastRequest.getClass()))
1576 {
1577 try
1578 {
1579 // XXX: May need to change the encoding based on codepage
1580 content += EncodingUtil.formUrlEncode(
1581 pairs, "ISO-8859-1") +
1582 " "; // Pad with a space to counter space stripping
1583 }
1584 catch (HttpClientError uee)
1585 {
1586 throw new MalformedURLException(uee.getMessage());
1587 }
1588 }
1589 else if (content != null)
1590 {
1591 if (method.equalsIgnoreCase("GET"))
1592 {
1593 if (! content.equals("?"))
1594 // pad content and don't try to include it in the body
1595 content += " ";
1596 }
1597 else
1598 {
1599 ((EntityEnclosingMethod)lastRequest).setRequestEntity(
1600 new StringRequestEntity(content));
1601 }
1602 }
1603 }
1604 catch (ClassCastException e)
1605 {
1606 // the error indicates that invalid options were specified on the
1607 // requested method, a request of this type cannot include a body
1608
1609 String msg = " Methods of type " + method + " cannot send " ;
1610
1611 if (files != null)
1612 msg += "files";
1613 else if (params != null)
1614 msg += "parameters";
1615 else if (content != null)
1616 msg += "body content";
1617
1618 throw new MalformedURLException(msg);
1619 }
1620
1621 if (method.equalsIgnoreCase("GET"))
1622 {
1623 content = content.substring(0, content.length() - 1);
1624
1625 if (!content.equals(""))
1626 lastRequest = new GetMethod(targetURL + content);
1627 }
1628
1629 // set auto follow redirects
1630 // do not set redirect if type is put or post - causes httpclient error
1631 boolean doRedirect = followRedirect;
1632
1633 // override the default setting
1634 if (redirect != null)
1635 doRedirect = redirect.booleanValue();
1636
1637 if (doRedirect &&
1638 ! method.equalsIgnoreCase("POST") &&
1639 ! method.equalsIgnoreCase("PUT") )
1640
1641 lastRequest.setFollowRedirects(true);
1642
1643 else
1644 lastRequest.setFollowRedirects(false);
1645
1646 int statusCode = -1;
1647
1648 // Retry up to 5 times for GET method requests
1649
1650 int numTries = 5;
1651
1652 if (method.equalsIgnoreCase("GET"))
1653 {
1654 // Create a new DefaultHttpMethodRetryHandler that retries up to
1655 // 5 times (instead of the default of 3 times) but does not retry
1656 // methods that have successfully sent their requests.
1657
1658 DefaultHttpMethodRetryHandler retryHandler =
1659 new DefaultHttpMethodRetryHandler(numTries, false);
1660
1661 session.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
1662 retryHandler);
1663 }
1664
1665 // Submit request
1666 try
1667 {
1668 if (HTTP.DEBUG)
1669 System.out.println(
1670 "WebSession.requestMethod(): Before " +
1671 "session.executeMethod(lastRequest)");
1672
1673 statusCode = session.executeMethod(lastRequest);
1674
1675 if (HTTP.DEBUG)
1676 System.out.println(
1677 "WebSession: requestMethod(): After " +
1678 "session.executeMethod(lastRequest)");
1679 }
1680 catch (URIException e)
1681 {
1682 // Indicates bad URL
1683 // Is this redundant with the constructor exception ?
1684 throw new MalformedURLException("Invalid URI " + targetURL);
1685 }
1686 catch (HttpException e)
1687 {
1688 // Indicates the request failed
1689 throw e;
1690 }
1691 catch (IOException e)
1692 {
1693 // Indicates page failed to download
1694 throw e;
1695 }
1696 catch (java.lang.IllegalArgumentException e)
1697 {
1698 // When URI is invalid
1699 throw new MalformedURLException("Invalid URI " + targetURL);
1700 }
1701 catch (java.lang.IllegalStateException e)
1702 {
1703 // When protocol of the absolute URI is not recognized
1704 throw new MalformedURLException("Invalid protocol " + targetURL);
1705 }
1706
1707 if (statusCode == -1)
1708 throw new HttpException ("Request Failed: Unknown Reason");
1709
1710 if (doRedirect && (statusCode > 299) && (statusCode < 400))
1711 {
1712 // this was a post or put request
1713 // redirect manually
1714 Header locationHeader = lastRequest.getResponseHeader("location");
1715 if (locationHeader != null)
1716 {
1717 String redirectLocation = locationHeader.getValue();
1718 requestMethod(redirectLocation, "GET",
1719 null, null, null, null,
1720 new Boolean(true), toFile, toMachine, false);
1721 }
1722 // should not reach here because 3xx return codes should have
1723 // a location header specifying the redirect url
1724 }
1725
1726 try
1727 {
1728 if (HTTP.DEBUG)
1729 System.out.println(
1730 "WebSession.requestMethod(): Before setCurrentContents(" +
1731 "lastRequest.getResponseBodyAsStream(), " + toFile +
1732 ", " + toMachine + ")");
1733
1734 setCurrentContents(lastRequest.getResponseBodyAsStream(),
1735 toFile, toMachine);
1736
1737 if (HTTP.DEBUG)
1738 System.out.println(
1739 "WebSession.requestMethod(): After setCurrentContents()");
1740 }
1741 catch(IOException e)
1742 {
1743 throw e;
1744 }
1745 catch(STAFException e)
1746 {
1747 throw e;
1748 }
1749 }
1750
1751 /*****************************************************************************/
1752 /* */
1753 /* Method: getHttpResponse */
1754 /* Description: Generate a string containing all information generated by the*/
1755 /* reply from the last interaction. It corresponds to the info */
1756 /* returned by the HTTP service 1.0.6 and earlier */
1757 /* Parameters: none */
1758 /* Returns: a string containing the specified content from the last */
1759 /* interaction */
1760 /* */
1761 /*****************************************************************************/
1762
getHttpResponse()1763 public HashMap getHttpResponse ()
1764 {
1765 HashMap response = new HashMap();
1766
1767 if (lastRequest == null) return response;
1768
1769 response.put(RETURN_STATUS_CODE, Integer.toString(getCurrentStatusCode()));
1770 response.put(RETURN_STATUS_MESSAGE, getCurrentStatusText());
1771
1772
1773 Header heads [] = lastRequest.getResponseHeaders() ;
1774 Map headers = new HashMap();
1775
1776 for (int i = 0; i < heads.length; i++)
1777 {
1778 // This may need to be changed to handle headers with multiple
1779 // values.
1780 headers.put(heads[i].getName(), heads[i].getValue());
1781 }
1782
1783 response.put(RETURN_HEADERS, headers);
1784
1785 return response;
1786 }
1787
1788 /*****************************************************************************/
1789 /* */
1790 /* Method: isOwner */
1791 /* Description: Determines if requester is the owner of the session by */
1792 /* Parameters: Requester's machine, process name, and handle */
1793 /* Returns: true if Owner and false if not owner */
1794 /* */
1795 /*****************************************************************************/
1796
isOwner(String reqInstanceUUID)1797 public boolean isOwner(String reqInstanceUUID)
1798 {
1799 if (reqInstanceUUID.equals(ownerInstanceUUID))
1800 {
1801 return true;
1802 }
1803 else
1804 {
1805 return false;
1806 }
1807 }
1808
1809 /*****************************************************************************/
1810 /* */
1811 /* Method: getSummary */
1812 /* Description: get a summary of the session. */
1813 /* Parameters: none */
1814 /* Returns: description of a session */
1815 /* */
1816 /*****************************************************************************/
1817
getSummary()1818 public HashMap getSummary()
1819 {
1820 HashMap summary = new HashMap();
1821
1822 summary.put(ID,Integer.toString(id));
1823 summary.put(TITLE, getCurrentTitle());
1824 summary.put(URL, getCurrentUrl());
1825 summary.put(RETURN_STATUS_CODE, Integer.toString(getCurrentStatusCode()));
1826 summary.put(RETURN_STATUS_MESSAGE, getCurrentStatusText());
1827 summary.put(POLICY, getCookiePolicy());
1828 if (followRedirect)
1829 summary.put(REQUEST_REDIRECT, "Enabled");
1830 else
1831 summary.put(REQUEST_REDIRECT, "Disabled");
1832 summary.put(PARSE_CONTENT, fParseContent);
1833 summary.put(HTTP_PROXY_HOST,
1834 session.getHostConfiguration().getProxyHost());
1835 summary.put(HTTP_PROXY_PORT,
1836 new Integer(session.getHostConfiguration().getProxyPort()));
1837 summary.put(OWNER_INSTANCE_UUID, ownerInstanceUUID);
1838 summary.put(OWNER_MACHINE, ownerMachine);
1839 summary.put(OWNER_HANDLE_NAME, ownerHandleName);
1840 summary.put(OWNER_HANDLE, Integer.toString(ownerHandle));
1841
1842 return summary;
1843 }
1844
1845 /*****************************************************************************/
1846 /* */
1847 /* Method: setDefaultHeader */
1848 /* Description: sets the value of the specifed default header to the */
1849 /* specified value */
1850 /* Parameters: name - key of the header */
1851 /* value - new value for the header */
1852 /* Returns: void */
1853 /* */
1854 /*****************************************************************************/
1855
setDefaultHeader(String name, String value)1856 public void setDefaultHeader(String name, String value)
1857 {
1858 try
1859 {
1860 String key = getDefaultHeaderKey(name);
1861 defaultHeaders.put(key, value);
1862 } catch (InvalidElementIDException e)
1863 {
1864 defaultHeaders.put(name, value);
1865 }
1866 }
1867
1868 /*****************************************************************************/
1869 /* */
1870 /* Method: deleteDefaultHeader */
1871 /* Description: remove the specifed default header */
1872 /* Parameters: name - key of the header */
1873 /* Returns: void */
1874 /* */
1875 /*****************************************************************************/
1876
deleteDefaultHeader(String name)1877 public void deleteDefaultHeader(String name)
1878 throws InvalidElementIDException
1879 {
1880 String key = getDefaultHeaderKey(name);
1881 defaultHeaders.remove(key);
1882 }
1883
1884 /*****************************************************************************/
1885 /* */
1886 /* Method: getDefaultHeaderKey */
1887 /* Description: get the key object of the specifed default header */
1888 /* Parameters: name - key of the header */
1889 /* Returns: key object to access the defaultHeader HashMap */
1890 /* */
1891 /*****************************************************************************/
1892
getDefaultHeaderKey(String name)1893 public String getDefaultHeaderKey(String name)
1894 throws InvalidElementIDException
1895 {
1896 Iterator it = defaultHeaders.keySet().iterator();
1897
1898 while(it.hasNext())
1899 {
1900 String key = (String) it.next();
1901 if (name.equalsIgnoreCase(key))
1902 return key;
1903 }
1904 throw new InvalidElementIDException (name, "Header key " + name);
1905 }
1906
1907 /*****************************************************************************/
1908 /* */
1909 /* Method: getDefaultHeaderValue */
1910 /* Description: get the value associated with the specifed default header */
1911 /* Parameters: name - key of the header */
1912 /* Returns: value assoicated with the defaultHeader */
1913 /* */
1914 /*****************************************************************************/
1915
getDefaultHeaderValue(String name)1916 public String getDefaultHeaderValue(String name)
1917 throws InvalidElementIDException
1918 {
1919 String key = getDefaultHeaderKey(name);
1920
1921 return (String)defaultHeaders.get(key);
1922 }
1923
1924 /*****************************************************************************/
1925 /* */
1926 /* Method: getDefaultHeaders */
1927 /* Description: get the HashMap storing the default header values */
1928 /* Parameters: none */
1929 /* Returns: the default header HashMap */
1930 /* */
1931 /*****************************************************************************/
1932
getDefaultHeaders()1933 public HashMap getDefaultHeaders()
1934 {
1935 return defaultHeaders;
1936 }
1937
1938 /*****************************************************************************/
1939 /* */
1940 /* Method: getDefaultFollowRedirect */
1941 /* Description: get if the session follows 3XX redirects by default or not */
1942 /* Parameters: none */
1943 /* Returns: if the session follows 3XX redirects by default or not */
1944 /* */
1945 /*****************************************************************************/
1946
getDefaultFollowRedirect()1947 public boolean getDefaultFollowRedirect()
1948 {
1949 return followRedirect;
1950 }
1951
1952 /*****************************************************************************/
1953 /* */
1954 /* Method: setDefaultFollowRedirect */
1955 /* Description: get if the session follows 3XX redirects by default or not */
1956 /* Parameters: redirect - if the session follows 3XX redirects by default or */
1957 /* not */
1958 /* Returns: void */
1959 /* */
1960 /*****************************************************************************/
1961
setDefaultFollowRedirect(boolean redirect)1962 public void setDefaultFollowRedirect(boolean redirect)
1963 {
1964 followRedirect = redirect;
1965 }
1966
1967 /*****************************************************************************/
1968 /* */
1969 /* Method: getParseContent */
1970 /* Description: Returns the value of fParseContent for the session */
1971 /* Parameters: none */
1972 /* Returns: A string containing Enabled, Disabled, or AutoDetect */
1973 /* */
1974 /*****************************************************************************/
1975
getParseContent()1976 public String getParseContent()
1977 {
1978 return fParseContent;
1979 }
1980
1981 /*****************************************************************************/
1982 /* */
1983 /* Method: setParseContent */
1984 /* Description: Sets if/how the session should parse content as HTML */
1985 /* Parameters: A string containing Enabled, Disabled, or AutoDetect, or an */
1986 /* invalid value */
1987 /* */
1988 /* Returns: STAFResult instance with RC == 0 if a valid parameter was input */
1989 /* STAFResult instance with RC != 0 and an error message in the */
1990 /* result if an invalid parameter was input */
1991 /* */
1992 /*****************************************************************************/
1993
setParseContent(String parseContent)1994 public STAFResult setParseContent(String parseContent)
1995 {
1996 // Verify that Enabled, Disabled, or AutoDetect was specified,
1997 // case-insensitive
1998
1999 if (parseContent.equalsIgnoreCase(ENABLED))
2000 {
2001 fParseContent = ENABLED;
2002 }
2003 else if (parseContent.equalsIgnoreCase(DISABLED))
2004 {
2005 fParseContent = DISABLED;
2006 }
2007 else if (parseContent.equalsIgnoreCase(AUTODETECT))
2008 {
2009 fParseContent = AUTODETECT;
2010 }
2011 else
2012 {
2013 return new STAFResult(
2014 STAFResult.InvalidValue,
2015 "PARSECONTENT option value must be Enabled, Disabled," +
2016 " or AutoDetect, case-insensitive. Invalid value: " +
2017 parseContent);
2018 }
2019
2020 return new STAFResult(STAFResult.Ok);
2021 }
2022
2023 /*****************************************************************************/
2024 /* */
2025 /* Method: setHttpProxy */
2026 /* Description: sets the HTTP Proxy host and port for the session, */
2027 /* Parameters: proxyHost - the HTTP Proxy host */
2028 /* proxyPort - the HTTP Proxy port (-1 indicates to use the */
2029 /* default port) */
2030 /* Returns: void */
2031 /* */
2032 /*****************************************************************************/
setHttpProxy(String proxyHost, int proxyPort)2033 public void setHttpProxy(String proxyHost, int proxyPort)
2034 {
2035 session.getHostConfiguration().setProxy(proxyHost, proxyPort);
2036 }
2037
2038 /*****************************************************************************/
2039 /* */
2040 /* Method: setAuthenticationSet */
2041 /* Description: sets the user and password for preemptive challenges to the */
2042 /* host */
2043 /* Parameters: host - the host to associate with this user and password */
2044 /* user - the user to assciate with this host */
2045 /* pwd - the password to assciate with this host */
2046 /* Returns: void */
2047 /* */
2048 /*****************************************************************************/
2049
setAuthenticationSet(String host, String user, String pwd, String domain)2050 public void setAuthenticationSet(String host, String user, String pwd,
2051 String domain)
2052 {
2053 String [] values = new String[3];
2054 values[0] = user;
2055 values[1] = pwd;
2056 values[2] = domain;
2057 try
2058 {
2059 String key = getAuthenticationSetKey(host);
2060 authenticationSets.put(key, values);
2061 } catch (InvalidElementIDException e)
2062 {
2063 authenticationSets.put(host, values);
2064 }
2065 }
2066
2067 /*****************************************************************************/
2068 /* */
2069 /* Method: deleteAuthenticationSet */
2070 /* Description: remove the specifed host */
2071 /* Parameters: host - the host to be removed */
2072 /* Returns: void */
2073 /* */
2074 /*****************************************************************************/
2075
deleteAuthenticationSet(String host)2076 public void deleteAuthenticationSet(String host)
2077 throws InvalidElementIDException
2078 {
2079 String key = getAuthenticationSetKey(host);
2080 authenticationSets.remove(key);
2081 }
2082
2083 /*****************************************************************************/
2084 /* */
2085 /* Method: getAuthenticationSetKey */
2086 /* Description: get the key object of the specifed host */
2087 /* Parameters: host - host string */
2088 /* Returns: key object to access the authenticationSet HashMap */
2089 /* */
2090 /*****************************************************************************/
2091
getAuthenticationSetKey(String host)2092 public String getAuthenticationSetKey(String host)
2093 throws InvalidElementIDException
2094 {
2095 Iterator it = authenticationSets.keySet().iterator();
2096
2097 while(it.hasNext())
2098 {
2099 String key = (String) it.next();
2100 if (host.equalsIgnoreCase(key))
2101 return key;
2102 }
2103 throw new InvalidElementIDException (host, "Authentication host key " + host);
2104 }
2105
2106 /*****************************************************************************/
2107 /* */
2108 /* Method: getAuthenticationSetValues */
2109 /* Description: get the value associated with the specifed host */
2110 /* Parameters: host - host assciated with the values */
2111 /* Returns: values assoicated with the host, [0] is user, [1] is password */
2112 /* */
2113 /*****************************************************************************/
2114
getAuthenticationSetValues(String host)2115 public String[] getAuthenticationSetValues(String host)
2116 throws InvalidElementIDException
2117 {
2118 String key = getAuthenticationSetKey(host);
2119
2120 return (String[]) authenticationSets.get(key);
2121 }
2122
2123 /*****************************************************************************/
2124 /* */
2125 /* Method: getAuthenticationSets */
2126 /* Description: get the HashMap storing the preemptive authentication values */
2127 /* Parameters: none */
2128 /* Returns: the authentication sets HashMap */
2129 /* */
2130 /*****************************************************************************/
2131
getAuthenticationSets()2132 public HashMap getAuthenticationSets()
2133 {
2134 return authenticationSets;
2135 }
2136
2137 /*****************************************************************************/
2138 /* */
2139 /* Method: resolveUrl */
2140 /* Description: clean up the url so that it is a full and absolute url */
2141 /* Parameters: targetURL - the url to be cleaned up */
2142 /* encoded - indicates whether the url is already encoded */
2143 /* (aka percent-encoded or percent-escaped) */
2144 /* Returns: the updated URL string */
2145 /* */
2146 /*****************************************************************************/
resolveUrl(String targetURL, boolean encoded)2147 protected String resolveUrl(String targetURL, boolean encoded)
2148 throws URIException
2149 {
2150 // An instance of the URI class is always in an "escaped" (aka
2151 // "encoded") form, since escaping or unescaping a completed URI might
2152 // change its semantics. Thus, we need to be careful not to escape or
2153 // unescape the same string more than once, since unescaping an
2154 // already unescaped string might lead to misinterpreting a percent
2155 // data character as another escaped character, or vice versa in the
2156 // case of escaping an already escaped string.
2157
2158 URI target = new URI(targetURL, encoded);
2159 URI absolute = null;
2160 String baseURL = getCurrentUrl();
2161
2162 if (target.isAbsoluteURI() || baseURL.equals(""))
2163 {
2164 // Set the absolute URL
2165 absolute = new URI(targetURL, encoded);
2166 }
2167 else
2168 {
2169 // Convert relative URL to an absolute URL
2170 URI base = new URI(baseURL, true);
2171 absolute = new URI(base, target);
2172 }
2173
2174 String absoluteURL = absolute.toString();
2175
2176 // Assume http protocol if no protocol specified
2177 if (absoluteURL.indexOf("://") == -1)
2178 absoluteURL = "http://" + absoluteURL;
2179
2180 return absoluteURL;
2181 }
2182
2183 }
2184
2185