/******************************************************************************* * Copyright (c) 2011 Subgraph. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Subgraph - initial API and implementation ******************************************************************************/ package com.subgraph.vega.ui.httpviewer; import org.apache.http.HttpEntity; import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.eclipse.jface.text.DocumentEvent; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IDocumentListener; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import com.subgraph.vega.api.http.requests.IHttpRequestBuilder; import com.subgraph.vega.api.http.requests.IHttpResponseBuilder; import com.subgraph.vega.ui.httpviewer.entity.HttpEntityViewer; public class HttpMessageViewer extends Composite { private final static String COLLAPSED_ICON = "icons/collapsed.png"; private final static String EXPANDED_ICON = "icons/expanded.png"; private final Colors colors; private final ImageCache imageCache = new ImageCache("com.subgraph.vega.ui.httpeditor"); private final Composite rootComposite; private final Label collapseButton; private final SourceViewer viewer; private final HttpMessageDocumentFactory documentFactory; private final HttpEntityViewer entityViewer; private final EmbeddedControlPainter painter; private IDocument rawDocument; private boolean isRawDocumentDirty; private IDocument decodedDocument; private boolean isDecodedDocumentDirty; private boolean isDecodingEnabled; private boolean isCollapsed; private boolean isEmpty; private boolean isEditable; public HttpMessageViewer(Composite parent) { super(parent, SWT.NONE); setLayout(new FillLayout()); setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE)); rootComposite = createRootComposite(); collapseButton = createCollapseHeaders(rootComposite); viewer = createSourceViewer(rootComposite); viewer.getTextWidget().setWrapIndent(20); entityViewer = new HttpEntityViewer(viewer.getTextWidget()); painter = new EmbeddedControlPainter(viewer, entityViewer, 200); viewer.addPainter(painter); colors = new Colors(getDisplay()); viewer.configure(new Configuration(colors)); documentFactory = new HttpMessageDocumentFactory(); layout(true); rootComposite.layout(true, true); } private Composite createRootComposite() { final Composite c = new Composite(this, SWT.NONE); final GridLayout layout = new GridLayout(2, false); layout.marginHeight = 0; layout.marginWidth = 0; layout.horizontalSpacing = 0; c.setLayout(layout); c.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE)); return c; } private Label createCollapseHeaders(Composite parent) { final Label button = new Label(parent, SWT.NONE); final GridData gd = new GridData(SWT.FILL, SWT.TOP, false, false); gd.widthHint = 16; gd.heightHint = 16; button.setLayoutData(gd); button.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE)); button.addMouseListener(new MouseAdapter() { @Override public void mouseDown(MouseEvent e) { toggleCollapseState(); } }); return button; } private void toggleCollapseState() { if(isEmpty) { return; } if(isCollapsed) { expandHeaders(); } else { collapseHeaders(); } } public void expandHeaders() { if(!isCollapsed || isEmpty) { return; } isCollapsed = false; collapseButton.setImage(imageCache.get(EXPANDED_ICON)); viewer.setEditable(isEditable); displayDocumentForDecodeState(); } public void collapseHeaders() { if(isCollapsed || isEmpty) { return; } isCollapsed = true; collapseButton.setImage(imageCache.get(COLLAPSED_ICON)); viewer.setEditable(false); displayDocumentForDecodeState(); } public void dispose() { colors.dispose(); super.dispose(); } public void setEditable(boolean flag) { isEditable = flag; viewer.setEditable(flag); } public void clearContent() { if (rawDocument != null) { rawDocument.set(""); isRawDocumentDirty = false; } if (decodedDocument != null) { decodedDocument.set(""); isDecodedDocumentDirty = false; } isDecodedDocumentDirty = false; isEmpty = true; entityViewer.clearContent(); collapseButton.setImage(null); viewer.refresh(); } public String getContent() { if(isDecodingEnabled) { return EmbeddedControlPainter.getDocumentContent(decodedDocument); } else { return EmbeddedControlPainter.getDocumentContent(rawDocument); } } public boolean isHeaderContentDirty() { if(isDecodingEnabled) { return isDecodedDocumentDirty; } else { return isRawDocumentDirty; } } public boolean isEntityContentDirty() { return entityViewer.isEntityContentDirty(); } public HttpEntity getEntityContent() { return entityViewer.getEntityContent(); } public void setDecodeUrlEncoding(boolean flag) { if(flag == isDecodingEnabled) { return; } isDecodingEnabled = flag; displayDocumentForDecodeState(); } private void displayDocumentForDecodeState() { if(isCollapsed) { viewer.setDocument(createCollapsedDocument()); } else if(isDecodingEnabled) { viewer.setDocument(decodedDocument); } else { viewer.setDocument(rawDocument); } viewer.refresh(); } private IDocument createCollapsedDocument() { if(isDecodingEnabled) { return createCollapsedDocument(decodedDocument); } else { return createCollapsedDocument(rawDocument); } } private IDocument createCollapsedDocument(IDocument current) { final String content = current.get(); final String[] lines = content.split("\n"); if(lines.length == 0) { return documentFactory.createDocumentForText(""); } else { return documentFactory.createDocumentForText(lines[0] + " ..."); } } private boolean isDocumentEmpty() { return rawDocument.get().trim().isEmpty(); } private void displayNewDocument() { isEmpty = isDocumentEmpty(); viewer.setEditable(isEditable); if(isEmpty) { collapseButton.setImage(null); } else if (isCollapsed) { collapseButton.setImage(imageCache.get(COLLAPSED_ICON)); } else { collapseButton.setImage(imageCache.get(EXPANDED_ICON)); } displayDocumentForDecodeState(); isRawDocumentDirty = false; isDecodedDocumentDirty = false; rawDocument.addDocumentListener(new IDocumentListener() { @Override public void documentChanged(DocumentEvent event) { } @Override public void documentAboutToBeChanged(DocumentEvent event) { isRawDocumentDirty = true; } }); decodedDocument.addDocumentListener(new IDocumentListener() { @Override public void documentAboutToBeChanged(DocumentEvent event) { } @Override public void documentChanged(DocumentEvent event) { isDecodedDocumentDirty = true; } }); } public void setDisplayImages(boolean flag) { entityViewer.setDisplayImages(flag); } public void setDisplayImagesAsHex(boolean flag) { entityViewer.setDisplayImagesAsHex(flag); } public void displayHttpRequest(HttpRequest request) { rawDocument = documentFactory.createDocumentForRequest(request, false); decodedDocument = documentFactory.createDocumentForRequest(request, true); displayNewDocument(); entityViewer.displayHttpEntity(maybeGetRequestEntity(request)); } public void displayHttpRequest(IHttpRequestBuilder builder) { rawDocument = documentFactory.createDocumentForRequest(builder, false); decodedDocument = documentFactory.createDocumentForRequest(builder, true); displayNewDocument(); entityViewer.displayHttpEntity(builder.getEntity()); } private HttpEntity maybeGetRequestEntity(HttpRequest request) { if(request instanceof HttpEntityEnclosingRequest) { return ((HttpEntityEnclosingRequest) request).getEntity(); } else { return null; } } public void displayHttpResponse(HttpResponse response) { rawDocument = documentFactory.createDocumentForResponse(response, false); decodedDocument = documentFactory.createDocumentForResponse(response, true); displayNewDocument(); entityViewer.displayHttpEntity(response.getEntity()); } public void displayHttpResponse(IHttpResponseBuilder builder) { rawDocument = documentFactory.createDocumentForResponse(builder, false); decodedDocument = documentFactory.createDocumentForResponse(builder, true); displayNewDocument(); entityViewer.displayHttpEntity(builder.getEntity()); } private SourceViewer createSourceViewer(Composite parent) { final SourceViewer sv = new SourceViewer(parent, null, SWT.MULTI | SWT.WRAP); final GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); sv.getControl().setLayoutData(gd); return sv; } }