/******************************************************************************* * 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.entity; import java.io.ByteArrayInputStream; import java.io.IOException; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.ParseException; import org.apache.http.util.EntityUtils; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.widgets.Composite; public class HttpEntityViewer extends Composite { private enum EntityDisplayMode { DISPLAY_EMPTY, DISPLAY_TEXT, DISPLAY_IMAGE, DISPLAY_BINARY }; private final StackLayout stack; private final HttpEntityImageViewer imageViewer; private final HttpEntityBinaryViewer binaryViewer; private final HttpEntityTextViewer textViewer; private final Composite emptyViewer; private boolean displayImages = true; private boolean displayImagesAsHex = false; private byte[] currentImageBytes; private ImageData currentImageData; private String currentImageContentType; private String currentImageContentEncoding; private EntityDisplayMode currentDisplayMode; private HttpEntity currentlyDisplayedEntity; public HttpEntityViewer(Composite parent) { super(parent, SWT.NONE); stack = new StackLayout(); setLayout(stack); textViewer = new HttpEntityTextViewer(this); imageViewer = new HttpEntityImageViewer(this); binaryViewer = new HttpEntityBinaryViewer(this); emptyViewer = createEmptyViewer(this); displayEmptyViewer(); } public void clearContent() { displayEmptyViewer(); } public void displayHttpEntity(HttpEntity entity) { currentlyDisplayedEntity = entity; if(entity == null || entity.getContentLength() == 0) { displayEmptyViewer(); return; } try { final String asString = EntityUtils.toString(entity); final String contentType = contentType(entity); final String contentEncoding = contentEncoding(entity); if(isBodyAscii(asString)) { displayTextViewer(asString, contentType, contentEncoding); return; } byte[] binary = EntityUtils.toByteArray(entity); if(binary == null || binary.length == 0) { displayEmptyViewer(); return; } final ImageData imageData = binaryToImageData(binary); if(imageData != null) { displayImageViewer(imageData, binary, contentType, contentEncoding); } else { displayHexViewer(binary, contentType, contentEncoding); } } catch (ParseException e) { displayEmptyViewer(); } catch (IOException e) { displayEmptyViewer(); } } public boolean isEntityContentDirty() { switch(currentDisplayMode) { case DISPLAY_IMAGE: case DISPLAY_BINARY: return binaryViewer.isContentDirty(); case DISPLAY_TEXT: return textViewer.isContentDirty(); case DISPLAY_EMPTY: default: return false; } } public HttpEntity getEntityContent() { if(currentDisplayMode == EntityDisplayMode.DISPLAY_TEXT && textViewer.isContentDirty()) { return textViewer.getEntityContent(); } else if ((currentDisplayMode == EntityDisplayMode.DISPLAY_IMAGE || currentDisplayMode == EntityDisplayMode.DISPLAY_BINARY) && binaryViewer.isContentDirty()) { return binaryViewer.getEntityContent(); } else { return currentlyDisplayedEntity; } } public void setDisplayImages(boolean flag) { if(flag != displayImages) { displayImages = flag; if(currentImageBytes != null && currentImageData != null) { displayImageViewerByFlags(); } } } public void setDisplayImagesAsHex(boolean flag) { if(flag != displayImagesAsHex) { displayImagesAsHex = flag; if(currentImageBytes != null && currentImageData != null) { displayImageViewerByFlags(); } } } private ImageData binaryToImageData(byte[] binary) { try { return new ImageData(new ByteArrayInputStream(binary)); } catch (SWTException e) { return null; } } private String contentType(HttpEntity entity) { final Header hdr = entity.getContentType(); if(hdr == null) return ""; else return hdr.getValue(); } private String contentEncoding(HttpEntity entity) { final Header hdr = entity.getContentEncoding(); if(hdr == null) { return ""; } else { return hdr.getValue(); } } private boolean isBodyAscii(String body) { if(body == null || body.isEmpty()) return false; final int total = (body.length() > 500) ? (500) : (body.length()); int printable = 0; for(int i = 0; i < total; i++) { char c = body.charAt(i); if((c >= 0x20 && c <= 0x7F) || Character.isWhitespace(c)) printable += 1; } return ((printable * 100) / total > 90); } private Composite createEmptyViewer(Composite parent) { final Composite viewer = new Composite(this, SWT.NONE); viewer.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE)); return viewer; } private void displayEmptyViewer() { currentDisplayMode = EntityDisplayMode.DISPLAY_EMPTY; resetViewers(); stack.topControl = emptyViewer; layout(); } private void displayTextViewer(String text, String contentType, String contentEncoding) { currentDisplayMode = EntityDisplayMode.DISPLAY_TEXT; resetViewers(); stack.topControl = textViewer; layout(); textViewer.setInput(text, contentType, contentEncoding); } private void displayImageViewer(ImageData imageData, byte[] imageBytes, String contentType, String contentEncoding) { currentDisplayMode = EntityDisplayMode.DISPLAY_IMAGE; resetViewers(); currentImageData = imageData; currentImageBytes = imageBytes; currentImageContentType = contentType; currentImageContentEncoding = contentEncoding; displayImageViewerByFlags(); } private void displayImageViewerByFlags() { if(!displayImages) { stack.topControl = emptyViewer; layout(); } else if(displayImagesAsHex) { stack.topControl = binaryViewer; layout(); binaryViewer.setInput(currentImageBytes, currentImageContentType, currentImageContentEncoding); } else { stack.topControl = imageViewer; layout(); imageViewer.setImage(currentImageData); } } private void displayHexViewer(byte[] data, String contentType, String contentEncoding) { currentDisplayMode = EntityDisplayMode.DISPLAY_BINARY; resetViewers(); stack.topControl = binaryViewer; layout(); binaryViewer.setInput(data, contentType, contentEncoding); } private void resetViewers() { textViewer.clear(); imageViewer.clear(); binaryViewer.clear(); currentImageBytes = null; currentImageData = null; currentImageContentType = null; currentImageContentEncoding = null; } }