001: package com.meterware.httpunit;
002:
003: /********************************************************************************************************************
004: * $Id: FrameHolder.java,v 1.15 2004/10/17 20:48:10 russgold Exp $
005: *
006: * Copyright (c) 2002-2004, Russell Gold
007: *
008: * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
009: * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
010: * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
011: * to permit persons to whom the Software is furnished to do so, subject to the following conditions:
012: *
013: * The above copyright notice and this permission notice shall be included in all copies or substantial portions
014: * of the Software.
015: *
016: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
017: * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
018: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
019: * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
020: * DEALINGS IN THE SOFTWARE.
021: *
022: *******************************************************************************************************************/
023: import java.io.IOException;
024: import java.net.MalformedURLException;
025: import java.util.*;
026:
027: import org.xml.sax.SAXException;
028:
029: /**
030: *
031: * @author <a href="mailto:russgold@httpunit.org">Russell Gold</a>
032: **/
033: class FrameHolder {
034:
035: /** Map from a frame selector to its corresponding web response. **/
036: private Hashtable _contents = new Hashtable();
037:
038: /** Map from a frame selector to its subframe selectors. **/
039: private Hashtable _subframes = new Hashtable();
040:
041: /** The window which owns this frame holder. **/
042: private WebWindow _window;
043:
044: /** The topmost frame in this frameholder. **/
045: private FrameSelector _topFrame;
046:
047: FrameHolder(WebWindow window) {
048: _window = window;
049: _topFrame = FrameSelector.newTopFrame(window);
050: DefaultWebResponse blankResponse = new DefaultWebResponse(
051: window.getClient(), null, WebResponse.BLANK_HTML);
052: _contents.put(_topFrame, blankResponse);
053: HttpUnitOptions.getScriptingEngine().associate(blankResponse);
054: }
055:
056: FrameSelector getTopFrame() {
057: return _topFrame;
058: }
059:
060: WebResponse getFrameContents(FrameSelector targetFrame) {
061: if (targetFrame == FrameSelector.TOP_FRAME)
062: targetFrame = getTopFrame();
063: WebResponse response = get(targetFrame);
064: if (response == null)
065: throw new NoSuchFrameException(targetFrame.getName());
066: return response;
067: }
068:
069: WebResponse getSubframeContents(FrameSelector frame,
070: String subFrameName) {
071: FrameSelector[] subframes = (FrameSelector[]) _subframes
072: .get(frame);
073: if (subframes == null)
074: throw new NoSuchFrameException(subFrameName);
075:
076: for (int i = 0; i < subframes.length; i++) {
077: FrameSelector subframe = subframes[i];
078: if (subframe.getName().equalsIgnoreCase(subFrameName))
079: return get(subframe);
080: }
081: throw new NoSuchFrameException(subFrameName);
082: }
083:
084: WebResponse getParentFrameContents(FrameSelector frame) {
085: return get(frame.getParent() == null ? _topFrame : frame
086: .getParent());
087: }
088:
089: WebResponse get(FrameSelector targetFrame) {
090: return (WebResponse) _contents.get(targetFrame);
091: }
092:
093: WebResponse get(String target) {
094: FrameSelector frame = getFrame(_topFrame, target);
095: return frame == null ? null : (WebResponse) _contents
096: .get(frame);
097: }
098:
099: FrameSelector getFrame(String target) {
100: return target.equals(_window.getName()) ? _topFrame : getFrame(
101: _topFrame, target);
102: }
103:
104: private FrameSelector getFrame(FrameSelector rootFrame,
105: String target) {
106: if (target.equalsIgnoreCase(WebRequest.TOP_FRAME))
107: return _topFrame;
108: if (target.equalsIgnoreCase(rootFrame.getName()))
109: return rootFrame;
110:
111: return lookupFrame(rootFrame, target);
112: }
113:
114: private FrameSelector lookupFrame(FrameSelector rootFrame,
115: String target) {
116: FrameSelector result = getFromSubframe(rootFrame, target);
117: if (result != null) {
118: return result;
119: } else if (rootFrame.getName().equals(target)) {
120: return rootFrame;
121: } else if (rootFrame.getParent() != null) {
122: return lookupFrame(rootFrame.getParent(), target);
123: } else {
124: return null;
125: }
126: }
127:
128: private FrameSelector getFromSubframe(FrameSelector rootFrame,
129: String target) {
130: FrameSelector[] subframes = (FrameSelector[]) _subframes
131: .get(rootFrame);
132: if (subframes == null)
133: return null;
134:
135: for (int i = 0; i < subframes.length; i++) {
136: if (subframes[i].getName().equalsIgnoreCase(target))
137: return subframes[i];
138: }
139: for (int i = 0; i < subframes.length; i++) {
140: FrameSelector result = getFromSubframe(subframes[i], target);
141: if (result != null)
142: return result;
143: }
144: return null;
145: }
146:
147: List getActiveFrameNames() {
148: List result = new ArrayList();
149: for (Enumeration e = _contents.keys(); e.hasMoreElements();) {
150: result.add(((FrameSelector) e.nextElement()).getName());
151: }
152:
153: return result;
154: }
155:
156: /**
157: * Determines the frame in which the reply to a request will be stored.
158: */
159: FrameSelector getTargetFrame(WebRequest request) {
160: if (WebRequest.NEW_WINDOW.equalsIgnoreCase(request.getTarget())) {
161: return FrameSelector.NEW_FRAME;
162: } else if (WebRequest.TOP_FRAME.equalsIgnoreCase(request
163: .getTarget())) {
164: return _topFrame;
165: } else if (WebRequest.SAME_FRAME.equalsIgnoreCase(request
166: .getTarget())) {
167: return request.getSourceFrame();
168: } else if (WebRequest.PARENT_FRAME.equalsIgnoreCase(request
169: .getTarget())) {
170: return request.getSourceFrame().getParent() == null ? _topFrame
171: : request.getSourceFrame().getParent();
172: } else if (request.getSourceFrame().getName().equalsIgnoreCase(
173: request.getTarget())) {
174: return request.getSourceFrame();
175: } else {
176: FrameSelector targetFrame = getFrame(request
177: .getSourceFrame(), request.getTarget());
178: if (targetFrame == null)
179: targetFrame = _window.getClient().findFrame(
180: request.getTarget());
181: return (targetFrame != null) ? targetFrame
182: : FrameSelector.NEW_FRAME;
183: }
184: }
185:
186: void updateFrames(WebResponse response, FrameSelector frame,
187: RequestContext requestContext)
188: throws MalformedURLException, IOException, SAXException {
189: removeSubFrames(frame);
190: _contents.put(frame, response);
191:
192: if (response.isHTML()) {
193: HttpUnitOptions.getScriptingEngine().associate(response);
194: requestContext.addNewResponse(response);
195: WebRequest[] requests = response.getFrameRequests();
196: if (requests.length > 0) {
197: createSubFrames(frame, response.getFrameSelectors());
198: for (int i = 0; i < requests.length; i++) {
199: if (requests[i].getURLString().length() != 0) {
200: response.getWindow().getSubframeResponse(
201: requests[i], requestContext);
202: }
203: }
204: }
205: }
206: }
207:
208: private void removeSubFrames(FrameSelector frame) {
209: FrameSelector[] subframes = (FrameSelector[]) _subframes
210: .get(frame);
211: if (subframes == null)
212: return;
213:
214: _subframes.remove(frame);
215: for (int i = 0; i < subframes.length; i++) {
216: removeSubFrames(subframes[i]);
217: _contents.remove(subframes[i]);
218: }
219: }
220:
221: private void createSubFrames(FrameSelector frame,
222: FrameSelector[] subframes) {
223: _subframes.put(frame, subframes);
224: for (int i = 0; i < subframes.length; i++) {
225: _contents.put(subframes[i], WebResponse
226: .createBlankResponse());
227: }
228: }
229:
230: /**
231: * Given the qualified name of a frame and the name of a nested frame, returns the qualified name of the nested frame.
232: */
233: static FrameSelector newNestedFrame(FrameSelector parentFrame,
234: final String relativeName) {
235: if (relativeName == null || relativeName.length() == 0)
236: return new FrameSelector();
237: return new FrameSelector(relativeName, parentFrame);
238: }
239:
240: }
|