/** * */ package com.grendelscan.commons.http.dataHandling.containers; import java.io.OutputStream; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; import org.apache.commons.lang.NotImplementedException; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPut; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.grendelscan.commons.StringUtils; import com.grendelscan.commons.http.HttpConstants; import com.grendelscan.commons.http.PrimaryQueryType; import com.grendelscan.commons.http.URIStringUtils; import com.grendelscan.commons.http.dataHandling.DataParser; import com.grendelscan.commons.http.dataHandling.data.AbstractData; import com.grendelscan.commons.http.dataHandling.data.Data; import com.grendelscan.commons.http.dataHandling.references.DataReference; import com.grendelscan.commons.http.dataHandling.references.DataReferenceChain; import com.grendelscan.commons.http.dataHandling.references.TransactionDataReference; import com.grendelscan.commons.http.transactions.StandardHttpTransaction; /** * @author david * */ public class TransactionContainer extends AbstractData implements DataContainer<TransactionDataReference> { private static final Logger LOGGER = LoggerFactory.getLogger(TransactionContainer.class); /** * */ private static final long serialVersionUID = 1L; private UrlEncodedQueryStringDataContainer urlQueryDataContainer; private Data bodyData; /** * @param parent * @param reference * @param transactionId */ public TransactionContainer(final int transactionId) { super(null, transactionId); parseData(); } /* * (non-Javadoc) * * @see com.grendelscan.commons.http.dataHandling.containers.DataContainer#childrenDebugString() */ @Override public String childrenDebugString() { StringBuilder sb = new StringBuilder(); sb.append("Transaction Container -\n"); sb.append(StringUtils.indentLines(abstractDataDebugString(), 1)); sb.append("\nURL container:\n"); if (urlQueryDataContainer == null) { sb.append("\t<null>"); } else { sb.append(StringUtils.indentLines(urlQueryDataContainer.debugString(), 1)); } sb.append("\nBody container:\n"); if (bodyData == null) { sb.append("\t<null>"); } else { sb.append(StringUtils.indentLines(bodyData.debugString(), 1)); } return sb.toString(); } private void createHtmlQueryContainer() { switch (getPrimaryQueryType()) { case MIME_MULTIPART: setBodyData(new MimeMultipartDataContainer(this, getTransaction().getRequestWrapper().getBody(), getTransactionId(), true)); return; case URL_ENCODED_BODY: // setBodyData(DataParser.parseRawData(getTransaction().getRequestWrapper().getBody(), this, // getTransaction().getRequestWrapper().getHeaders().getMimeType(), getTransactionId(), false)); setBodyData(new UrlEncodedQueryStringDataContainer(this, getTransaction().getRequestWrapper().getBody(), getTransactionId(), true)); return; case URL_QUERY: String query = ""; try { query = URIStringUtils.getQuery(getTransaction().getRequestWrapper().getURI()); } catch (URISyntaxException e) { LOGGER.error("Problem parsing URI query (" + getTransaction().getRequestWrapper().getURI() + ": " + e.toString(), e); } setUrlQueryDataContainer(new UrlEncodedQueryStringDataContainer(this, query.getBytes(), getTransactionId(), true)); return; } } /* * (non-Javadoc) * * @see com.grendelscan.commons.http.dataHandling.data.Data#debugString() */ @Override public String debugString() { StringBuilder sb = new StringBuilder(); sb.append("TransactionContainer:\n"); sb.append(StringUtils.indentLines(abstractDataDebugString(), 1)); sb.append("\n"); sb.append(StringUtils.indentLines(childrenDebugString(), 1)); return sb.toString(); } public final Data getBodyData() { return bodyData; } /* * (non-Javadoc) * * @see com.grendelscan.commons.http.dataHandling.containers.DataContainer#getChild(com.grendelscan.commons.http.dataHandling.references.DataReference) */ @Override public Data getChild(final TransactionDataReference reference) { if (reference.isBody()) { return getBodyData(); } return getUrlQueryDataContainer(); } /* * (non-Javadoc) * * @see com.grendelscan.commons.http.dataHandling.containers.DataContainer#getChildsReference(com.grendelscan.commons.http.dataHandling.data.Data) */ @Override public TransactionDataReference getChildsReference(final Data child) { if (child == bodyData) { return TransactionDataReference.REQUEST_BODY; } else if (child == urlQueryDataContainer) { return TransactionDataReference.URL_QUERY; } throw new IllegalArgumentException("The passed data object is not a child of this container"); } /* * (non-Javadoc) * * @see com.grendelscan.commons.http.dataHandling.containers.DataContainer#getChildUnsafeType(com.grendelscan.commons.http.dataHandling.references.DataReference) */ @Override public Data getChildUnsafeType(final DataReference reference) { return getChild((TransactionDataReference) reference); } /* * (non-Javadoc) * * @see com.grendelscan.commons.http.dataHandling.containers.DataContainer#getDataChildren() */ @Override public Data[] getDataChildren() { List<Data> data = new ArrayList<Data>(2); if (urlQueryDataContainer != null) { data.add(urlQueryDataContainer); } if (bodyData != null) { data.add(bodyData); } return data.toArray(new Data[0]); } public HtmlQueryContainer<?> getHtmlQueryContainer() { switch (getPrimaryQueryType()) { case URL_ENCODED_BODY: case MIME_MULTIPART: return (HtmlQueryContainer<?>) getBodyData(); case URL_QUERY: return getUrlQueryDataContainer(); } throw new NotImplementedException("This query type is unknown: " + getPrimaryQueryType().toString()); } public synchronized HtmlQueryContainer<?> getOrCreateHtmlQueryContainer() { if (getHtmlQueryContainer() == null) { createHtmlQueryContainer(); } return getHtmlQueryContainer(); } /* * (non-Javadoc) * * @see com.grendelscan.commons.http.dataHandling.data.Data#getParent() */ @Override public DataContainer<?> getParent() { return null; } public PrimaryQueryType getPrimaryQueryType() { if (getTransaction().getRequestWrapper().getMethod().equals(HttpPost.METHOD_NAME) || getTransaction().getRequestWrapper().getMethod().equals(HttpPut.METHOD_NAME)) { String mime = getTransaction().getRequestWrapper().getHeaders().getMimeType().toLowerCase(); if (mime.equals(HttpConstants.ENCODING_APPLICATION_X_WWW_FORM_URLENCODED)) { return PrimaryQueryType.URL_ENCODED_BODY; } else if (mime.equals(HttpConstants.ENCODING_MULTIPART_FORM_DATA)) { return PrimaryQueryType.MIME_MULTIPART; } } return PrimaryQueryType.URL_QUERY; } /* * (non-Javadoc) * * @see com.grendelscan.commons.http.dataHandling.data.Data#getReference() */ @Override public DataReference getReference() { throw new NotImplementedException("Not implemented at the transaction level"); } /* * (non-Javadoc) * * @see com.grendelscan.commons.http.dataHandling.data.Data#getReferenceChain() */ @Override public DataReferenceChain getReferenceChain() { throw new NotImplementedException("Not implemented at the transaction level"); } // /* (non-Javadoc) // * @see com.grendelscan.commons.http.dataHandling.data.Data#clone(int) // */ // @Override // public Data clone(TransactionContainer transaction) // { // throw new NotImplementedException("Not implemented at the transaction level"); // } private StandardHttpTransaction getTransaction() { return Scan.getInstance().getTransactionRecord().getTransaction(getTransactionId()); } public final UrlEncodedQueryStringDataContainer getUrlQueryDataContainer() { return urlQueryDataContainer; } /* * (non-Javadoc) * * @see com.grendelscan.commons.http.dataHandling.data.Data#isAncestor(com.grendelscan.commons.http.dataHandling.containers.DataContainer) */ @Override public boolean isDataAncestor(@SuppressWarnings("unused") final DataContainer<?> container) { throw new NotImplementedException("Not implemented at the transaction level"); } private synchronized void parseData() { StandardHttpTransaction transaction = getTransaction(); byte[] body = transaction.getRequestWrapper().getBody(); if (body != null && body.length > 0) { setBodyData(DataParser.parseRawData(body, this, transaction.getRequestWrapper().getHeaders().getMimeType(), getTransactionId(), true)); } try { byte[] urlQuery = URIStringUtils.getQuery(transaction.getRequestWrapper().getURI()).getBytes(); if (urlQuery != null && urlQuery.length > 0) { setUrlQueryDataContainer(new UrlEncodedQueryStringDataContainer(this, urlQuery, getTransactionId(), true)); } } catch (URISyntaxException e) { e.printStackTrace(); } } /* * (non-Javadoc) * * @see com.grendelscan.commons.http.dataHandling.containers.DataContainer#removeChild(com.grendelscan.commons.http.dataHandling.data.Data) */ @Override public void removeChild(@SuppressWarnings("unused") final Data child) { throw new NotImplementedException("Not implemented at the transaction level"); } /* * (non-Javadoc) * * @see com.grendelscan.commons.http.dataHandling.data.Data#removeFromCollection() */ @Override public void removeFromCollection() { throw new NotImplementedException("Not implemented at the transaction level"); } /* * (non-Javadoc) * * @see com.grendelscan.commons.http.dataHandling.containers.DataContainer#replaceChild(com.grendelscan.commons.http.dataHandling.references.DataReference, * com.grendelscan.commons.http.dataHandling.data.Data) */ @Override public void replaceChild(final TransactionDataReference reference, final Data child) { if (reference.isBody()) { setBodyData(child); } else { if (child instanceof UrlEncodedQueryStringDataContainer) { setUrlQueryDataContainer((UrlEncodedQueryStringDataContainer) child); } else { throw new IllegalArgumentException("Child must be UrlEncodedQueryStringDataContainer"); } } } protected final void setBodyData(final Data bodyData) { this.bodyData = bodyData; } protected final void setUrlQueryDataContainer(final UrlEncodedQueryStringDataContainer urlQueryDataContainer) { this.urlQueryDataContainer = urlQueryDataContainer; } /* * (non-Javadoc) * * @see com.grendelscan.commons.http.dataHandling.data.Data#writeBytes(java.io.OutputStream) */ @Override public void writeBytes(final OutputStream out) { throw new NotImplementedException("Not implemented at the transaction level"); } }