Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * */ package org.apache.directory.studio.ldapbrowser.common.dialogs; import java.io.File; import java.io.IOException; import java.nio.charset.StandardCharsets; import org.apache.directory.api.util.FileUtils; import org.apache.directory.studio.connection.ui.ConnectionUIPlugin; import org.apache.directory.studio.ldapbrowser.common.BrowserCommonActivator; import org.apache.directory.studio.ldapbrowser.common.BrowserCommonConstants; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; /** * Dialog to display binary data in hex format. It could be * used to load and save binary data from and to disk. * * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> */ public class HexDialog extends Dialog { /** The default title. */ private static final String DIALOG_TITLE = Messages.getString("HexDialog.HexEditor"); //$NON-NLS-1$ /** The button ID for the edit as text button. */ private static final int EDIT_AS_TEXT_BUTTON_ID = 9997; /** The button ID for the load button. */ private static final int LOAD_BUTTON_ID = 9998; /** The button ID for the save button. */ private static final int SAVE_BUTTON_ID = 9999; /** The current data. */ private byte[] currentData; /** The return data. */ private byte[] returnData; /** The text field with the binary data. */ private Text hexText; /** * Creates a new instance of HexDialog. * * @param parentShell the parent shell * @param initialData the initial data */ public HexDialog(Shell parentShell, byte[] initialData) { super(parentShell); super.setShellStyle(super.getShellStyle() | SWT.RESIZE); this.currentData = initialData; } /** * @see org.eclipse.jface.dialogs.Dialog#buttonPressed(int) */ protected void buttonPressed(int buttonId) { if (buttonId == IDialogConstants.OK_ID) { returnData = currentData; } else if (buttonId == EDIT_AS_TEXT_BUTTON_ID) { TextDialog dialog = new TextDialog(getShell(), new String(currentData, StandardCharsets.UTF_8)); if (dialog.open() == TextDialog.OK) { String text = dialog.getText(); currentData = text.getBytes(StandardCharsets.UTF_8); hexText.setText(toFormattedHex(currentData)); } } else if (buttonId == SAVE_BUTTON_ID) { FileDialog fileDialog = new FileDialog(getShell(), SWT.SAVE); fileDialog.setText(Messages.getString("HexDialog.SaveData")); //$NON-NLS-1$ String returnedFileName = fileDialog.open(); if (returnedFileName != null) { try { File file = new File(returnedFileName); FileUtils.writeByteArrayToFile(file, currentData); } catch (IOException e) { ConnectionUIPlugin.getDefault().getExceptionHandler() .handleException(new Status(IStatus.ERROR, BrowserCommonConstants.PLUGIN_ID, IStatus.ERROR, Messages.getString("HexDialog.CantWriteToFile"), e)); //$NON-NLS-1$ } } } else if (buttonId == LOAD_BUTTON_ID) { FileDialog fileDialog = new FileDialog(getShell(), SWT.OPEN); fileDialog.setText(Messages.getString("HexDialog.LoadData")); //$NON-NLS-1$ String returnedFileName = fileDialog.open(); if (returnedFileName != null) { try { File file = new File(returnedFileName); currentData = FileUtils.readFileToByteArray(file); hexText.setText(toFormattedHex(currentData)); } catch (IOException e) { ConnectionUIPlugin.getDefault().getExceptionHandler() .handleException(new Status(IStatus.ERROR, BrowserCommonConstants.PLUGIN_ID, IStatus.ERROR, Messages.getString("HexDialog.CantReadFile"), e)); //$NON-NLS-1$ } } } else { returnData = null; } super.buttonPressed(buttonId); } /** * Small helper. */ private boolean isEditable(byte[] b) { if (b == null) { return false; } return !(new String(b, StandardCharsets.UTF_8).contains("\uFFFD")); } /** * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell) */ protected void configureShell(Shell shell) { super.configureShell(shell); shell.setText(DIALOG_TITLE); shell.setImage(BrowserCommonActivator.getDefault().getImage(BrowserCommonConstants.IMG_HEXEDITOR)); } /** * @see org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse.swt.widgets.Composite) */ protected void createButtonsForButtonBar(Composite parent) { if (isEditable(currentData)) { createButton(parent, EDIT_AS_TEXT_BUTTON_ID, Messages.getString("HexDialog.EditAsText"), false); //$NON-NLS-1$ } createButton(parent, LOAD_BUTTON_ID, Messages.getString("HexDialog.LoadDataButton"), false); //$NON-NLS-1$ createButton(parent, SAVE_BUTTON_ID, Messages.getString("HexDialog.SaveDataButton"), false); //$NON-NLS-1$ createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, false); createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); } /** * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite) */ protected Control createDialogArea(Composite parent) { // create composite Composite composite = (Composite) super.createDialogArea(parent); hexText = new Text(composite, SWT.MULTI | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.READ_ONLY); hexText.setFont(JFaceResources.getFont(JFaceResources.TEXT_FONT)); hexText.setText(toFormattedHex(currentData)); GridData gd = new GridData(GridData.FILL_BOTH); gd.widthHint = convertHorizontalDLUsToPixels((int) (IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH * 1.4)); gd.heightHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH / 2); hexText.setLayoutData(gd); applyDialogFont(composite); return composite; } /** * Formats the binary data in two columns. One containing the hex * presentation and one containing the ASCII presentation of each byte. * * 91 a1 08 23 42 b1 c1 15 52 d1 f0 24 33 62 72 82 ...#B... R..$3br. * 09 0a 16 17 18 19 1a 25 26 27 28 29 2a 34 35 36 .......% &'()*456 * * @param data the data * * @return the formatted string */ private String toFormattedHex(byte[] data) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < data.length; i++) { // get byte int b = (int) data[i]; if (b < 0) { b = 256 + b; } // format to hex, optionally prepend a 0 String s = Integer.toHexString(b); if (s.length() == 1) { s = "0" + s; //$NON-NLS-1$ } // space between hex numbers sb.append(s).append(" "); //$NON-NLS-1$ // extra space after 8 hex numbers if ((i + 1) % 8 == 0) { sb.append(" "); //$NON-NLS-1$ } // if end of data is reached then fill with spaces if (i == data.length - 1) { while ((i + 1) % 16 != 0) { sb.append(" "); //$NON-NLS-1$ if ((i + 1) % 8 == 0) { sb.append(" "); //$NON-NLS-1$ } i++; } sb.append(" "); //$NON-NLS-1$ } // print ASCII characters after 16 hex numbers if ((i + 1) % 16 == 0) { sb.append(" "); //$NON-NLS-1$ for (int x = i - 16 + 1; x <= i && x < data.length; x++) { // print ASCII charachter if printable // otherwise print a dot if (data[x] > 32 && data[x] < 127) { sb.append((char) data[x]); } else { sb.append('.'); } // space after 8 characters if ((x + 1) % 8 == 0) { sb.append(" "); //$NON-NLS-1$ } } } // start new line after 16 hex numbers if ((i + 1) % 16 == 0) { sb.append("\r\n"); //$NON-NLS-1$ } } return sb.toString(); } /** * Gets the data. * * @return the data */ public byte[] getData() { return returnData; } }