/*
* GNU LESSER GENERAL PUBLIC LICENSE Copyright (C) 2006 The Lobo Project This
* library is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version. This library is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details. You should have received a copy of
* the GNU Lesser General Public License along with this library; if not, write
* to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
* MA 02110-1301 USA Contact info: lobochief@users.sourceforge.net
*/
/*
* Created on Oct 22, 2005
*/
package com.nvarghese.beowulf.common.cobra.html.test;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.w3c.dom.html2.HTMLCollection;
import org.w3c.dom.html2.HTMLElement;
import org.w3c.dom.html2.HTMLLinkElement;
import com.nvarghese.beowulf.common.cobra.html.BrowserFrame;
import com.nvarghese.beowulf.common.cobra.html.FormInput;
import com.nvarghese.beowulf.common.cobra.html.HtmlObject;
import com.nvarghese.beowulf.common.cobra.html.HtmlRendererContext;
import com.nvarghese.beowulf.common.cobra.html.UserAgentContext;
import com.nvarghese.beowulf.common.cobra.html.domimpl.FrameNode;
import com.nvarghese.beowulf.common.cobra.html.domimpl.HTMLDocumentImpl;
import com.nvarghese.beowulf.common.cobra.html.parser.DocumentBuilderImpl;
import com.nvarghese.beowulf.common.cobra.html.parser.InputSourceImpl;
import com.nvarghese.beowulf.common.cobra.util.Urls;
import com.nvarghese.beowulf.common.cobra.util.io.RecordedInputStream;
import com.nvarghese.beowulf.common.http.renderer.CobraUserAgent;
import com.nvarghese.beowulf.common.http.txn.AbstractHttpTransaction;
/**
* The <code>SimpleHtmlRendererContext</code> class implements the
* {@link com.nvarghese.beowulf.common.cobra.html.HtmlRendererContext}
* interface. Note that this class provides rudimentary implementations of most
* callback methods. Overridding some of the methods in this class will usually
* be necessary in a professional application.
* <p>
* A simple way to load a URL into the {@link HtmlPanel} of the renderer context
* is to invoke {@link #navigate(String)}.
*/
public class SimpleHtmlRendererContext implements HtmlRendererContext {
private static final Logger logger = Logger.getLogger(SimpleHtmlRendererContext.class.getName());
// private final HtmlPanel htmlPanel;
private final HtmlRendererContext parentRcontext;
private static final Set mediaNames = new HashSet();
static {
// Media names claimed by this context.
Set mn = mediaNames;
mn.add("screen");
mn.add("tv");
mn.add("tty");
mn.add("all");
}
/**
* Constructs a SimpleHtmlRendererContext.
*/
public SimpleHtmlRendererContext() {
this((UserAgentContext) null);
}
/**
* Constructs a SimpleHtmlRendererContext.
*
* @param contextComponent
* The component that will render HTML.
* @see SimpleUserAgentContext
*/
public SimpleHtmlRendererContext(final UserAgentContext ucontext) {
super();
// this.htmlPanel = contextComponent;
this.parentRcontext = null;
this.bcontext = ucontext;
}
/**
* Constructs a SimpleHtmlRendererContext that is a child of another
* <code>{@link HtmlRendererContext}</code>.
*
* @param contextComponent
* The component that will render HTML.
* @param parentRcontext
* The parent's renderer context.
*/
public SimpleHtmlRendererContext(final HtmlRendererContext parentRcontext) {
super();
this.parentRcontext = parentRcontext;
this.bcontext = parentRcontext == null ? null : parentRcontext.getUserAgentContext();
}
public SimpleHtmlRendererContext(final UserAgentContext ucontext, final HtmlRendererContext parentRcontext) {
this.parentRcontext = parentRcontext;
this.bcontext = ucontext;
}
/*
* public HtmlPanel getHtmlPanel() { return this.htmlPanel; }
*/
private volatile String sourceCode;
/**
* Gets the source code of the current HTML document.
*/
public String getSourceCode() {
return this.sourceCode;
}
/**
* Gets a collection of current document frames, by querying the document
* currently held by the local {@link org.cobra_grendel.html.gui.HtmlPanel}
* instance. Currently Disabled.
*/
public HTMLCollection getFrames() {
return null;
/*
* Object rootNode = this.htmlPanel.getRootNode(); if(rootNode
* instanceof HTMLDocumentImpl) { return ((HTMLDocumentImpl)
* rootNode).getFrames(); } else { return null; }
*/
}
/**
* Implements reload as navigation to current URL. Override to implement a
* more robust reloading mechanism. Disabled currently.
*/
public void reload() {
/*
* HTMLDocumentImpl document = (HTMLDocumentImpl)
* this.htmlPanel.getRootNode(); if(document != null) { try { URL url =
* new URL(document.getDocumentURI()); this.navigate(url, null); }
* catch(java.net.MalformedURLException throwable) {
* this.warn("reload(): Malformed URL", throwable); } }
*/
}
/**
* Implements the link click handler by invoking
* {@link #navigate(URL, String)}.
*/
public void linkClicked(final HTMLElement linkNode, final URL url, final String target) {
this.navigate(url, target);
}
/**
* Gets the connection proxy used in {@link #navigate(URL, String)}. This
* implementation calls {@link SimpleUserAgentContext#getProxy()} if
* {@link #getUserAgentContext()} returns an instance assignable to
* {@link SimpleUserAgentContext}. The method may be overridden to provide a
* different proxy setting.
*/
protected Proxy getProxy() {
Object ucontext = this.getUserAgentContext();
if (ucontext instanceof SimpleUserAgentContext) {
return ((SimpleUserAgentContext) ucontext).getProxy();
}
return Proxy.NO_PROXY;
}
/**
* Implements simple navigation with incremental rendering by invoking
* {@link #submitForm(String, URL, String, String, FormInput[])} with a
* <code>GET</code> request method.
*/
// public void navigate(final URL href, String target) {
// this.submitForm("GET", href, target, null, null);
// }
/**
* Implements simple navigation with incremental rendering, and target
* processing, including frame lookup. Should be overridden to allow for
* more robust browser navigation.
* <p>
* <b>Notes:</b>
* <ul>
* <li>Encoding ISO-8859-1 assumed always.
* <li>Caching is not implemented.
* <li>Cookies are not implemented.
* <li>Incremental rendering is not optimized for ignorable document change
* notifications.
* <li>Other HTTP features are not implemented.
* </ul>
*/
public void navigate(final URL href, String target) {
// This method implements simple incremental rendering.
if (target != null) {
HtmlRendererContext topCtx = getTop();
HTMLCollection frames = topCtx.getFrames();
if (frames != null) {
org.w3c.dom.Node frame = frames.namedItem(target);
if (frame instanceof FrameNode) {
BrowserFrame bframe = ((FrameNode) frame).getBrowserFrame();
if (bframe == null) {
throw new IllegalStateException("Frame node without a BrowserFrame instance: " + frame);
}
if (bframe.getHtmlRendererContext() != this) {
bframe.loadURL(href);
return;
}
}
}
target = target.trim().toLowerCase();
if ("_top".equals(target)) {
getTop().navigate(href, null);
return;
} else if ("_parent".equals(target)) {
HtmlRendererContext parent = getParent();
if (parent != null) {
parent.navigate(href, null);
return;
}
} else if ("_blank".equals(target)) {
this.open(href.toExternalForm(), "cobra.blank", "", false);
return;
} else {
// fall through
}
}
URL urlForLoading;
if (href.getProtocol().equals("file")) {
// Remove query so it works.
try {
urlForLoading = new URL(href.getProtocol(), href.getHost(), href.getPort(), href.getPath());
} catch (java.net.MalformedURLException throwable) {
this.warn("malformed", throwable);
urlForLoading = href;
}
} else {
urlForLoading = href;
}
final URL finalURLForLoading = urlForLoading;
CobraUserAgent uaContext = (CobraUserAgent) this.getUserAgentContext();
URI requestURI = null;
try {
requestURI = urlForLoading.toURI();
} catch (URISyntaxException e) {
logger.warning("navigate(): Error in converting URL to URI for uri=" + urlForLoading);
}
int transactionId = -1;
boolean wasRequested = false;
String username = "";
AbstractHttpTransaction rawTransaction = null;
final long time0 = System.currentTimeMillis();
if (requestURI != null) {
// try {
//
// username = "";
// //TODO:
// //username =
// uaContext.getScan().getTransactionRecord().getTransaction(uaContext.getId()).getUsername();
//
// if(username != null && !username.equalsIgnoreCase("")) {
// transactionId =
// uaContext.getScan().getTransactionRecord().getTransactionId("GET",
// finalURLForLoading.toString(), username);
//
// wasRequested =
// uaContext.getScan().getTransactionRecord().isUriRequested("GET",
// finalURLForLoading.toString(), username, false);
// } else {
// transactionId =
// uaContext.getScan().getTransactionRecord().getTransactionId("GET",
// finalURLForLoading.toString(), null);
//
// wasRequested =
// uaContext.getScan().getTransactionRecord().isUriRequested("GET",
// finalURLForLoading.toString(), null, false);
// }
//
/*
* Possibility of 4 cases Case 1: wasRequested = True, transactionId
* > 0 This means we can fetch the request from Cache/DB Case 2:
* wasRequested = False, transactionId < 0 This means the request is
* new. So we have to take care of it here and also add it for
* spidering Case 3: wasRequested = False, transactionId > 0 This is
* a Race condition. Very uncertain, unpredicatble and with low
* probability. Case 4: wasRequested = True, transactionId < 0 This
* is also a Race condition. This state happens when spidering added
* the URL and before the transaction was saved to DB. Cache DB
* add/update/refresh happens just after the transaction is saved to
* DB
*/
// if (transactionId == -1 && !wasRequested) {
// /*
// * Solves Case 2 If the transaction is not in cache and if
// * it was not requested before, add it to the requester
// * queue for spidering
// */
// rawTransaction =
// HttpTransactionFactory.createTransaction(uaContext.getScan(),
// "GET", requestURI,
// uaContext.getId(), TransactionSource.COBRA);
// // Debug.debug("Debug: raw ID: " + rawTransaction.getId() +
// // " rawUri: " + rawTransaction.getMethod() + " " +
// // rawTransaction.getAbsoluteUriString() +
// // " Reason_ren: No cache");
// TransactionSource referenceTransactionSource =
// uaContext.getScan().getTransactionRecord()
// .getTransaction(uaContext.getId()).getSource();
// if (referenceTransactionSource != TransactionSource.TEST) {
// uaContext.getScan().getRequesterQueue().addSpiderRequest(rawTransaction,
// false,
// "Javascript: Asynchronous Requests ");
// }
//
// } else if (transactionId > 0) {
// /*
// * Solves Case 1 and Case 3 If the request is found in
// * cache, then fetch it and continue
// */
// rawTransaction =
// uaContext.getScan().getTransactionRecord().getTransaction(transactionId);
// // Debug.debug("Debug: raw ID: " + rawTransaction.getId() +
// // " rawUri: " + rawTransaction.getMethod() + " "
// // +rawTransaction.getAbsoluteUriString() +
// // " Reason_ren: Cache hit");
//
// } else if (transactionId == -1 && wasRequested) {
// /*
// * Solves Case 4 1. Wait to complete the processing by
// * requesterThread? or 2. Duplicate request Currently
// * duplicating.
// */
// rawTransaction =
// HttpTransactionFactory.createTransaction(uaContext.getScan(),
// "GET", requestURI,
// uaContext.getId(), TransactionSource.COBRA);
// // Debug.debug("Debug: raw ID: " + rawTransaction.getId() +
// // " rawUri: " + rawTransaction.getMethod() + " " +
// // rawTransaction.getAbsoluteUriString() +
// // " Reason_ren: No cache, but requested");
// }
//
// if (rawTransaction != null) {
// synchronized (rawTransaction) {
//
// /*
// * Solves uncertain conditions
// */
//
// if (!rawTransaction.isResponsePresent() ||
// !rawTransaction.isSuccessfullExecution()) {
//
// /*
// * This should solve uncertain conditions like -
// * Transaction from cache/DB might not have response
// * - A newly created transaction which is not
// * executed
// */
//
// rawTransaction.execute("CobraHttpRequest", false);
//
// } else {
//
//
// /*
// * Load it from cache
// */
//
// }
// }
// }
//
// } catch (Exception e) {
// // TODO: handle exception
// }
//
}
final AbstractHttpTransaction finalTransaction = rawTransaction;
// Make request asynchronously.
new Thread() {
@Override
public void run() {
try {
URL uri = href;
logger.info("process(): Loading URI=[" + uri + "].");
if (finalTransaction != null) {
// try {
// sourceCode = null;
// long time1 = System.currentTimeMillis();
// byte[] input = finalTransaction.getResponseBody();
// if (input != null) {
// ByteArrayInputStream inputStream = new
// ByteArrayInputStream(input);
// InputSource inputSource = new
// InputSourceImpl(inputStream,
// finalTransaction.getURI()
// , finalTransaction.getContentType().getCharset());
//
// DocumentBuilderImpl builder = new
// DocumentBuilderImpl(SimpleHtmlRendererContext.this
// .getUserAgentContext(),
// SimpleHtmlRendererContext.this);
//
// if (inputSource != null) {
// HTMLDocumentImpl document = (HTMLDocumentImpl)
// builder.createDocument(inputSource);
// // Now start loading.
// document.load();
// long time2 = System.currentTimeMillis();
// logger.info("Parsed URI=[" + uri +
// "]: Parse elapsed: " + (time2 - time1)
// + " ms. Fetched from Cache/DB: " + (time1 - time0) +
// " ms.");
// sourceCode = inputStream.toString();
// }
//
// }
// } finally {
//
// }
} else {
/*
* The last ditch effort using java libraries
*/
// Using potentially different URL for loading.
URLConnection connection = finalURLForLoading.openConnection();
connection.setRequestProperty("User-Agent", getUserAgentContext().getUserAgent());
connection.setRequestProperty("Cookie", "");
if (connection instanceof HttpURLConnection) {
HttpURLConnection hc = (HttpURLConnection) connection;
hc.setInstanceFollowRedirects(true);
int responseCode = hc.getResponseCode();
logger.info("process(): HTTP response code: " + responseCode);
}
InputStream in = connection.getInputStream();
try {
sourceCode = null;
long time1 = System.currentTimeMillis();
RecordedInputStream rin = new RecordedInputStream(in, 8192);
InputStream bin = new BufferedInputStream(rin, 8192);
// HtmlParserContext pcontext =
// createParserContext(uri);
// SimpleUserAgentContext ucontext = new
// SimpleUserAgentContext();
DocumentBuilderImpl builder = new DocumentBuilderImpl(SimpleHtmlRendererContext.this.getUserAgentContext(),
SimpleHtmlRendererContext.this);
String actualURI = uri.toExternalForm();
// Only create document, don't parse.
HTMLDocumentImpl document = (HTMLDocumentImpl) builder.createDocument(new InputSourceImpl(bin, actualURI, "ISO-8859-1"));
// Set document in HtmlPanel. Safe to call outside
// GUI
// thread.
// SimpleHtmlRendererContext.this.htmlPanel.setDocument(document,
// SimpleHtmlRendererContext.this);
// Now start loading.
document.load();
long time2 = System.currentTimeMillis();
logger.info("Parsed URI=[" + uri + "]: Parse elapsed: " + (time2 - time1) + " ms. Connection elapsed: " + (time1 - time0)
+ " ms.");
sourceCode = rin.getString("ISO-8859-1");
} finally {
in.close();
}
}
} catch (Exception err) {
SimpleHtmlRendererContext.this.error("navigate(): Error loading or parsing request.", err);
}
}
}.start();
}
/**
* Convenience method provided to allow loading a document into the
* renderer.
*
* @param fullURL
* The absolute URL of the document.
* @see #navigate(URL, String)
*/
public void navigate(final String fullURL) throws java.net.MalformedURLException {
java.net.URL href = Urls.createURL(null, fullURL);
this.navigate(href, "_this");
}
/**
* Redirects form submission through scanner. Disabled other features for
* incremental rendering. Original Text follows: Implements simple
* navigation and form submission with incremental rendering and target
* processing, including frame lookup. Should be overridden to allow for
* more robust browser navigation and form submission. Use
* #navigate(URL,String)
* <p>
* <b>Notes:</b>
* <ul>
* <li>Document encoding is defined by
* {@link #getDocumentCharset(URLConnection)}.
* <li>Caching is not implemented.
* <li>Cookies are not implemented.
* <li>Incremental rendering is not optimized for ignorable document change
* notifications.
* <li>Other HTTP features are not implemented.
* <li>The only form encoding type supported is
* <code>application/x-www-form-urlencoded</code>.
* <li>Navigation is normally asynchronous. See
* {@link #isNavigationAsynchronous()}.
* </ul>
*
* @see #navigate(URL, String)
*/
public void submitForm(final String method, final java.net.URL action, final String target, final String enctype, final FormInput[] formInputs) {
/*
* StringBuffer sb = new StringBuffer(); String lineBreak =
* System.getProperty("line.separator"); if (formInputs != null) { for
* (int i = 0; i < formInputs.length; i++) { sb.append("INPUT: " +
* formInputs[i].toString()); sb.append(lineBreak); } }
* //this.warn("submitForm(): Not overridden; method=" + method +
* "; action=" + action + "; target=" + target // + "; enctype=" +
* enctype + lineBreak + sb);
*/
// URI actionURI = null;
// AbstractStandardHttpTransaction request = null;
// CobraUserAgent uaContext = (CobraUserAgent)
// this.getUserAgentContext();
// try {
// actionURI = action.toURI();
// } catch (URISyntaxException e) {
// this.warn("submitForm(): Error in converting URL to URI for action="
// + action);
//
// }
//
// try {
// request =
// HttpTransactionFactory.createTransaction(uaContext.getScan(), method,
// actionURI, uaContext
// .getId(), TransactionSource.SPIDER);
// if (formInputs != null) {
// String defaultText =
// ConfigurationManager.getString("default_form_values.default_text");
// List<String> formParamsList =
// ConfigurationManager.getList("default_form_values.params_list");
// for (int i = 0; i < formInputs.length; i++) {
// if (formInputs[i].isText() &&
// !(formInputs[i].getTextValue().equalsIgnoreCase(""))) {
// request.addQueryParameter(formInputs[i].getName(),
// formInputs[i].getTextValue());
// } else {
// request.addQueryParameter(formInputs[i].getName(),
// ConfigurationManager.getString(
// "default_form_values." + getConfigparam(formInputs[i].getName(),
// formParamsList),
// formInputs[i].getName() + defaultText));
// }
// }
// }
//
// uaContext.getScan().getRequesterQueue().addSpiderRequest(request,
// false, "Javascript: Form Submit() ");
// } catch (URISyntaxException e) {
//
// this.warn("URI syntax problem in (" + action + "): " + e.toString());
// }
}
/*
* public void submitForm(final String method, final java.net.URL action,
* final String target, final String enctype, final FormInput[] formInputs)
* { // This method implements simple incremental rendering. if(target !=
* null) { HtmlRendererContext topCtx = this.getTop(); HTMLCollection frames
* = topCtx.getFrames(); if(frames != null) { org.w3c.dom.Node frame =
* frames.namedItem(target); if(logger.isLoggable(Level.INFO)) {
* logger.info("submitForm(): Frame matching target=" + target + " is " +
* frame); } if(frame instanceof FrameNode) { BrowserFrame bframe =
* ((FrameNode) frame).getBrowserFrame(); if(bframe == null) { throw new
* IllegalStateException("Frame node without a BrowserFrame instance: " +
* frame); } if(bframe.getHtmlRendererContext() != this) {
* bframe.loadURL(action); return; } } } String actualTarget =
* target.trim().toLowerCase(); if("_top".equals(actualTarget)) {
* this.getTop().navigate(action, null); return; } else if
* ("_parent".equals(actualTarget)) { HtmlRendererContext parent =
* this.getParent(); if(parent != null) { parent.navigate(action, null);
* return; } } else if("_blank".equals(actualTarget)) { this.open(action,
* "cobra.blank", "", false); return; } else
* if("_this".equals(actualTarget)) { // fall through } else {
* logger.warning("submitForm(): Link target unrecognized: " +
* actualTarget); } } // Make request asynchronously.
* if(this.isNavigationAsynchronous()) { new Thread() { public void run() {
* try { SimpleHtmlRendererContext.this.submitFormSync(method, action,
* target, enctype, formInputs); } catch (Exception err) {
* SimpleHtmlRendererContext.this.error(
* "navigate(): Error loading or parsing request.", err); } } }.start(); }
* else { try { SimpleHtmlRendererContext.this.submitFormSync(method,
* action, target, enctype, formInputs); } catch (Exception err) {
* SimpleHtmlRendererContext.this.error(
* "navigate(): Error loading or parsing request.", err); } } }
*/
private String getConfigparam(final String formParam, final List<String> formParamList) {
for (String param : formParamList) {
if (formParam.toLowerCase().contains(param)) {
return param;
}
}
return formParam;
}
/**
* Indicates whether navigation (via
* {@link #submitForm(String, URL, String, String, FormInput[])}) should be
* asynchronous. This overridable implementation returns <code>true</code>.
*/
protected boolean isNavigationAsynchronous() {
return true;
}
/**
* The connection currently opened by openSync() if any.
*/
protected URLConnection currentConnection;
/**
* Submits a form and/or navigates by making a <i>synchronous</i> request.
* This method is invoked by
* {@link #submitForm(String, URL, String, String, FormInput[])}.
*
* @param method
* The request method.
* @param action
* The action URL.
* @param target
* The target identifier.
* @param enctype
* The encoding type.
* @param formInputs
* The form inputs.
* @throws IOException
* @throws org.xml.sax.SAXException
* @see #submitForm(String, URL, String, String, FormInput[])
*/
/*
* protected void submitFormSync(final String method, final java.net.URL
* action, final String target, String enctype, final FormInput[]
* formInputs) throws IOException, org.xml.sax.SAXException { final String
* actualMethod = method.toUpperCase(); URL resolvedURL;
* if("GET".equals(actualMethod) && formInputs != null) { boolean firstParam
* = true; //TODO: What about the userInfo part of the URL? URL noRefAction
* = new URL(action.getProtocol(), action.getHost(), action.getPort(),
* action.getFile()); StringBuffer newUrlBuffer = new
* StringBuffer(noRefAction.toExternalForm()); if(action.getQuery() == null)
* { newUrlBuffer.append("?"); } else { newUrlBuffer.append("&"); } for(int
* i = 0; i < formInputs.length; i++) { FormInput parameter = formInputs[i];
* String name = parameter.getName(); String encName =
* URLEncoder.encode(name, "UTF-8"); if(parameter.isText()) { if(firstParam)
* { firstParam = false; } else { newUrlBuffer.append("&"); } String
* valueStr = parameter.getTextValue(); String encValue =
* URLEncoder.encode(valueStr, "UTF-8"); newUrlBuffer.append(encName);
* newUrlBuffer.append("="); newUrlBuffer.append(encValue); } else {
* logger.warning("postData(): Ignoring non-textual parameter " + name +
* " for GET."); } } resolvedURL = new
* java.net.URL(newUrlBuffer.toString()); } else { resolvedURL = action; }
* URL urlForLoading; if(resolvedURL.getProtocol().equalsIgnoreCase("file"))
* { // Remove query so it works. try { String ref = action.getRef(); String
* refText = ref == null || ref.length() == 0 ? "" : "#" + ref;
* urlForLoading = new URL(resolvedURL.getProtocol(), action.getHost(),
* action.getPort(), action.getPath() + refText); }
* catch(java.net.MalformedURLException throwable) { this.warn("malformed",
* throwable); urlForLoading = action; } } else { urlForLoading =
* resolvedURL; } if(logger.isLoggable(Level.INFO)) {
* logger.info("process(): Loading URI=[" + urlForLoading + "]."); } long
* time0 = System.currentTimeMillis(); // Using potentially different URL
* for loading. Proxy proxy = SimpleHtmlRendererContext.this.getProxy();
* boolean isPost = "POST".equals(actualMethod); URLConnection connection =
* proxy == null || proxy == Proxy.NO_PROXY ? urlForLoading.openConnection()
* : urlForLoading.openConnection(proxy); this.currentConnection =
* connection; try { connection.setRequestProperty("User-Agent",
* getUserAgentContext().getUserAgent());
* connection.setRequestProperty("Cookie", ""); if (connection instanceof
* HttpURLConnection) { HttpURLConnection hc = (HttpURLConnection)
* connection; hc.setRequestMethod(actualMethod);
* hc.setInstanceFollowRedirects(false); } if(isPost) {
* connection.setDoOutput(true); ByteArrayOutputStream bufOut = new
* ByteArrayOutputStream(); boolean firstParam = true; if(formInputs !=
* null) { for(int i = 0; i < formInputs.length; i++) { FormInput parameter
* = formInputs[i]; String name = parameter.getName(); String encName =
* URLEncoder.encode(name, "UTF-8"); if(parameter.isText()) { if(firstParam)
* { firstParam = false; } else { bufOut.write((byte) '&'); } String
* valueStr = parameter.getTextValue(); String encValue =
* URLEncoder.encode(valueStr, "UTF-8");
* bufOut.write(encName.getBytes("UTF-8")); bufOut.write((byte) '=');
* bufOut.write(encValue.getBytes("UTF-8")); } else {
* logger.warning("postData(): Ignoring non-textual parameter " + name +
* " for POST."); } } } // Do not add a line break to post content. Some
* servers // can be picky about that (namely, java.net). byte[] postContent
* = bufOut.toByteArray(); if(connection instanceof HttpURLConnection) {
* ((HttpURLConnection)
* connection).setFixedLengthStreamingMode(postContent.length); }
* connection.setRequestProperty("Content-Type",
* "application/x-www-form-urlencoded");
* //connection.setRequestProperty("Content-Length",
* String.valueOf(postContent.length)); OutputStream postOut =
* connection.getOutputStream(); postOut.write(postContent);
* postOut.flush(); } if (connection instanceof HttpURLConnection) {
* HttpURLConnection hc = (HttpURLConnection) connection; int responseCode =
* hc.getResponseCode(); if(logger.isLoggable(Level.INFO)) {
* logger.info("process(): HTTP response code: " + responseCode); }
* if(responseCode == HttpURLConnection.HTTP_MOVED_PERM || responseCode ==
* HttpURLConnection.HTTP_MOVED_TEMP || responseCode ==
* HttpURLConnection.HTTP_SEE_OTHER) { String location =
* hc.getHeaderField("Location"); if(location == null) {
* logger.warning("No Location header in redirect from " + action + "."); }
* else { java.net.URL href; href = Urls.createURL(action, location);
* SimpleHtmlRendererContext.this.navigate(href, target); } return; } }
* InputStream in = connection.getInputStream(); try {
* SimpleHtmlRendererContext.this.sourceCode = null; long time1 =
* System.currentTimeMillis(); RecordedInputStream rin = new
* RecordedInputStream(in, 1000000); InputStream bin = new
* BufferedInputStream(rin, 8192); String actualURI =
* urlForLoading.toExternalForm(); // Only create document, don't parse.
* HTMLDocumentImpl document = this.createDocument(new InputSourceImpl(bin,
* actualURI, getDocumentCharset(connection))); // Set document in
* HtmlPanel. Safe to call outside GUI thread. HtmlPanel panel = htmlPanel;
* panel.setDocument(document, SimpleHtmlRendererContext.this); // Now start
* loading. document.load(); long time2 = System.currentTimeMillis();
* if(logger.isLoggable(Level.INFO)) { logger.info("Parsed URI=[" +
* urlForLoading + "]: Parse elapsed: " + (time2 - time1) +
* " ms. Connection elapsed: " + (time1 - time0) + " ms."); } String ref =
* urlForLoading.getRef(); if(ref != null && ref.length() != 0) {
* panel.scrollToElement(ref); } try {
* SimpleHtmlRendererContext.this.sourceCode = rin.getString("ISO-8859-1");
* } catch(BufferExceededException bee) {
* SimpleHtmlRendererContext.this.sourceCode = "[TOO BIG]"; } } finally {
* in.close(); } } finally { this.currentConnection = null; } }
*/
/**
* Creates a blank document instance. This method is invoked whenever
* navigation or form submission occur. It is provided so it can be
* overridden to create specialized document implmentations.
*
* @param inputSource
* The document input source.
* @throws IOException
* @throws org.xml.sax.SAXException
*/
protected HTMLDocumentImpl createDocument(final org.xml.sax.InputSource inputSource) throws IOException, org.xml.sax.SAXException {
DocumentBuilderImpl builder = new DocumentBuilderImpl(this.getUserAgentContext(), SimpleHtmlRendererContext.this);
return (HTMLDocumentImpl) builder.createDocument(inputSource);
}
/**
* This method is invoked by
* {@link #submitForm(String, URL, String, String, FormInput[])} to
* determine the charset of a document. The charset is determined by looking
* at the <code>Content-Type</code> header.
*
* @param connection
* A URL connection.
*/
protected String getDocumentCharset(final URLConnection connection) {
String encoding = Urls.getCharset(connection);
return encoding == null ? "ISO-8859-1" : encoding;
}
// Methods useful to Window below:
/**
* Opens a simple message dialog. Currently Disabled.
*/
public void alert(final String message) {
}
/**
* It should give up focus on the current browser window. This
* implementation does nothing and should be overridden.
*/
public void blur() {
this.warn("back(): Not overridden");
}
/**
* It should close the current browser window. This implementation does
* nothing and should be overridden.
*/
public void close() {
this.warn("close(): Not overridden");
}
/**
* Opens a simple confirmation window.
*/
public boolean confirm(final String message) {
return true;
/*
* int retValue = JOptionPane.showConfirmDialog(htmlPanel, message,
* "Confirm", JOptionPane.YES_NO_OPTION); return retValue ==
* JOptionPane.YES_OPTION;
*/
}
/**
* It should request focus for the current browser window. This
* implementation does nothing and should be overridden.
*/
public void focus() {
this.warn("focus(): Not overridden");
}
/**
* @deprecated Use {@link #open(URL, String, String, boolean)}.
*/
public final HtmlRendererContext open(String url, String windowName, String windowFeatures, boolean replace) {
URL urlObj;
try {
urlObj = new URL(url);
} catch (MalformedURLException mfu) {
throw new IllegalArgumentException("Malformed URL: " + url);
}
return this.open(urlObj, windowName, windowFeatures, replace);
}
/**
* It should open a new browser window. This implementation does nothing and
* should be overridden.
*
* @param url
* The requested URL.
* @param windowName
* A window identifier.
* @param windowFeatures
* Window features specified in a format equivalent to that of
* window.open() in Javascript.
* @param replace
* Whether an existing window with the same name should be
* replaced.
*/
public HtmlRendererContext open(java.net.URL url, String windowName, String windowFeatures, boolean replace) {
// this.warn("open(): Not overridden");
boolean wasRequested = false;
AbstractHttpTransaction rawTransaction = null;
CobraUserAgent uaContext = (CobraUserAgent) this.getUserAgentContext();
if (url != null) {
// try {
//
// String username =
// uaContext.getScan().getTransactionRecord().getTransaction(uaContext.getId()).getUsername();
// if(username == null) {
// username = "";
// }
// wasRequested =
// uaContext.getScan().getTransactionRecord().isUriRequested("GET",
// url.toString(), username, false);
//
// /*
// * A cache look-up is not required here
// */
//
// if (!wasRequested) {
// /*
// * If the request was not requested before, add it to the
// * requester queue for spidering
// */
// rawTransaction =
// HttpTransactionFactory.createTransaction(uaContext.getScan(),
// "GET", url.toURI(),
// uaContext.getId(), TransactionSource.COBRA);
// // Debug.debug("Debug: raw ID: " + rawTransaction.getId() +
// // " rawUri: " + rawTransaction.getMethod() + " " +
// // rawTransaction.getAbsoluteUriString() +
// // " Reason_ren: No cache");
// TransactionSource referenceTransactionSource =
// uaContext.getScan().getTransactionRecord()
// .getTransaction(uaContext.getId()).getSource();
// if (referenceTransactionSource != TransactionSource.TEST) {
// uaContext.getScan().getRequesterQueue().addSpiderRequest(rawTransaction,
// false,
// "Javascript: Window.open ");
// }
//
// }
//
// } catch (Exception e) {
// // TODO: handle exception
// }
}
return null;
}
/**
* Shows a simple prompt dialog.
*/
public String prompt(String message, String inputDefault) {
return "";
}
/*
* public String prompt(String message, String inputDefault) { return
* JOptionPane.showInputDialog(htmlPanel, message); }
*/
/**
* Changes the origin of the HTML block's scrollable area according to the
* position given.
* <p>
* This method may be called outside of the GUI thread. The operation is
* scheduled immediately in that thread as needed.
*
* @param x
* The new x coordinate for the origin.
* @param y
* The new y coordinate for the origin.
*/
/*
* public void scroll(int x, int y) { this.htmlPanel.scroll(x, y); } public
* void scrollBy(int x, int y) { this.htmlPanel.scrollBy(x, y); }
*/
/**
* Should return true if and only if the current browser window is closed.
* This implementation returns false and should be overridden.
*/
public boolean isClosed() {
this.warn("isClosed(): Not overridden");
return false;
}
/**
* Should return true if and only if the current browser window is closed.
* This implementation returns false and should be overridden.
*/
public String getDefaultStatus() {
this.warn("getDefaultStatus(): Not overridden");
return "";
}
/**
* It should return the name of the browser window, if this renderer context
* is for the top frame in the window. This implementation returns a blank
* string, so it should be overridden.
*/
public String getName() {
this.warn("getName(): Not overridden");
return "";
}
public HtmlRendererContext getParent() {
return this.parentRcontext;
}
private volatile HtmlRendererContext opener;
public HtmlRendererContext getOpener() {
return this.opener;
}
public void setOpener(HtmlRendererContext opener) {
this.opener = opener;
}
public String getStatus() {
this.warn("getStatus(): Not overridden");
return "";
}
public void setStatus(String message) {
this.warn("setStatus(): Not overridden");
}
public HtmlRendererContext getTop() {
HtmlRendererContext ancestor = this.parentRcontext;
if (ancestor == null) {
return this;
}
return ancestor.getTop();
}
public BrowserFrame createBrowserFrame() {
return null;
// return new SimpleBrowserFrame(this);
}
public void warn(String message, Throwable throwable) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, message, throwable);
}
}
public void error(String message, Throwable throwable) {
if (logger.isLoggable(Level.SEVERE)) {
logger.log(Level.SEVERE, message, throwable);
}
}
public void warn(String message) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, message);
}
}
public void error(String message) {
if (logger.isLoggable(Level.SEVERE)) {
logger.log(Level.SEVERE, message);
}
}
/**
* Returns <code>null</code>. This method should be overridden to provide
* OBJECT, EMBED or APPLET functionality.
*/
public HtmlObject getHtmlObject(HTMLElement element) {
// Retaining old cobra_grendel implementation
HtmlObject result;
if ("OBJECT".equalsIgnoreCase(element.getTagName())) {
result = null;
} else {
result = new SimpleHtmlObject(element);
}
this.warn("getHtmlObject(): Not overridden; returning " + result + " for " + element + ".");
return result;
}
/*
* public HtmlObject getHtmlObject(HTMLElement element) { return null; }
*/
public void setDefaultStatus(String message) {
this.warn("setDefaultStatus(): Not overridden.");
}
private UserAgentContext bcontext = null;
/**
* If a {@link com.nvarghese.beowulf.common.cobra.html.UserAgentContext}
* instance was provided in the constructor, then that instance is returned.
* Otherwise, an instance of {@link SimpleUserAgentContext} is created and
* returned.
* <p>
* The context returned by this method is used by local request facilities
* and other parts of the renderer.
*/
public UserAgentContext getUserAgentContext() {
synchronized (this) {
if (this.bcontext == null) {
this.warn("getUserAgentContext(): UserAgentContext not provided in constructor. Creating a simple one.");
this.bcontext = new SimpleUserAgentContext();
}
return this.bcontext;
}
}
/**
* Should be overridden to return true if the link has been visited.
*/
public boolean isVisitedLink(final HTMLLinkElement link) {
return false;
}
/**
* This method must be overridden to implement a context menu.
*/
public boolean onContextMenu(final HTMLElement element, final MouseEvent event) {
return true;
}
/**
* This method can be overridden to receive notifications when the mouse
* leaves an element.
*/
public void onMouseOut(final HTMLElement element, final MouseEvent event) {
}
/**
* This method can be overridden to receive notifications when the mouse
* first enters an element.
*/
public void onMouseOver(final HTMLElement element, final MouseEvent event) {
}
public boolean isImageLoadingEnabled() {
return true;
}
public boolean onDoubleClick(final HTMLElement element, final MouseEvent event) {
return true;
}
public boolean onMouseClick(final HTMLElement element, final MouseEvent event) {
return true;
}
private static java.awt.Window getWindow(final Component c) {
java.awt.Component current = c;
while (current != null && !(current instanceof java.awt.Window)) {
current = current.getParent();
}
return (java.awt.Window) current;
}
/*
* public void resizeBy(int byWidth, int byHeight) { java.awt.Window window
* = getWindow(this.htmlPanel); if(window != null) {
* window.setSize(window.getWidth() + byWidth, window.getHeight() +
* byHeight); } }
*/
/*
* public void resizeTo(int width, int height) { java.awt.Window window =
* getWindow(this.htmlPanel); if(window != null) { window.setSize(width,
* height); } }
*/
/**
* It should navigate back one page. This implementation does nothing and
* should be overridden.
*/
public void back() {
/*
* if(logger.isLoggable(Level.WARNING)) { logger.log(Level.WARNING,
* "back() does nothing, unless overridden."); }
*/
}
public void forward() {
/*
* if(logger.isLoggable(Level.WARNING)) { logger.log(Level.WARNING,
* "forward() does nothing, unless overridden."); }
*/
}
/*
* public String getCurrentURL() { Object node =
* this.htmlPanel.getRootNode(); if(node instanceof HTMLDocumentImpl) {
* HTMLDocumentImpl doc = (HTMLDocumentImpl) node; return
* doc.getDocumentURI(); } return null; }
*/
public int getHistoryLength() {
return 0;
}
public String getNextURL() {
return null;
}
public String getPreviousURL() {
return null;
}
public void goToHistoryURL(final String url) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, "goToHistoryURL() does nothing, unless overridden.");
}
}
public void moveInHistory(final int offset) {
if (logger.isLoggable(Level.WARNING)) {
logger.log(Level.WARNING, "moveInHistory() does nothing, unless overridden.");
}
}
@Override
public String getCurrentURL() {
// TODO Auto-generated method stub
return null;
}
@Override
public void resizeBy(final int byWidth, final int byHeight) {
// TODO Auto-generated method stub
}
@Override
public void resizeTo(final int width, final int height) {
// TODO Auto-generated method stub
}
@Override
public void scroll(final int x, final int y) {
// TODO Auto-generated method stub
}
@Override
public void scrollBy(final int x, final int y) {
// TODO Auto-generated method stub
}
}