KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ca > directory > jxplorer > editor > basicbinaryeditor


1 package com.ca.directory.jxplorer.editor;
2
3 import com.ca.commons.cbutil.*;
4 import com.ca.directory.jxplorer.JXplorer;
5 import com.ca.directory.jxplorer.HelpIDs;
6 import com.ca.commons.naming.DN;
7 import javax.swing.*;
8 import java.awt.*;
9 import java.awt.event.*;
10 import java.io.*;
11 import java.util.Arrays JavaDoc;
12 import java.util.logging.Logger JavaDoc;
13 import java.util.logging.Level JavaDoc;
14
15
16
17 /**
18 * Sets up a binary editor that displays the binary data in hex format.
19 * The user can load, save and edit the data . By default the editor displays
20 * the first 1000 characters of the data. The edit button allows the user
21 * to view/edit the whole file.
22 */

23
24 public class basicbinaryeditor extends JDialog
25     implements abstractbinaryeditor
26 {
27     protected editablebinary editMe = null;
28     protected JTextArea field;
29     protected CBButton btnLoad, btnSave, btnView, btnOK, btnCancel, btnHelp, btnEdit;
30     protected Frame frame; // application frame, used to display dialog boxes.
31
protected CBPanel display; // the panel that components are displayed on.
32
protected boolean editHex; //TE: hex edit flag that checks if all hex is displayed, (or if the 'edit' button has been clicked).
33
protected StringBuffer JavaDoc hex; //TE: the converted bytes into a hex string.
34
protected byte[] bytes; //TE: global variable for the entry that is being either loaded, save or edited it is also used as the source for setting the value in the table editor if the user is not in edit mode (this would mean the value is unchanged).
35
protected byte[] oldBytes; //TE: copy of the data from the directory.
36
protected DN currentDN = null; //TE: the dn of the current entry.
37

38
39     private static final String JavaDoc NODATAMSG = "No data available"; //TE: constant variable that is displayed in text editor (usually) if no value is available.
40

41     //private static String lastDirectory = null;
42

43
44     // default to certificate viewer, need to add the filename at the end
45
private String JavaDoc viewCommand = "rundll32.exe cryptext.dll,CryptExtOpenCER ";
46
47     private final static Logger JavaDoc log = Logger.getLogger(basicbinaryeditor.class.getName());
48
49
50    /**
51     * Constructor.
52     * @param owner handle to the application frame, used to display dialog boxes.
53     */

54
55     public basicbinaryeditor(Frame owner)
56     {
57         this(owner, false);
58     }
59
60
61
62    /**
63     * Sets up the frame with one panel, one scrollable text area and six buttons.
64     * @param owner handle to the application frame, used to display dialog boxes.
65     * @param viewable specifies if there is a viewer for the binary data, if true, the "view" button is added to the panel.
66     */

67
68     public basicbinaryeditor(Frame owner, boolean viewable)
69     {
70         super(owner);
71         setModal(true);
72         setTitle(CBIntText.get("Binary Data"));
73
74         editHex = false;
75
76         display = new CBPanel();
77
78         addMainViewComponent();
79
80         btnView = new CBButton(CBIntText.get("View"), CBIntText.get(""));
81         btnView.addActionListener(new ActionListener() {
82                     public void actionPerformed(ActionEvent e) {
83                         view();
84         }});
85
86         btnLoad = new CBButton(CBIntText.get("Load"), CBIntText.get("Click here to load an external file."));
87         btnLoad.addActionListener(new ActionListener() {
88                     public void actionPerformed(ActionEvent e) {
89                         load();
90         }});
91
92         btnSave = new CBButton(CBIntText.get("Save"), CBIntText.get("Click here to save the date to an external file."));
93         btnSave.addActionListener(new ActionListener() {
94                     public void actionPerformed(ActionEvent e) {
95                         save();
96         }});
97
98         btnOK = new CBButton(CBIntText.get("OK"), CBIntText.get("Click here to make the changes (remember to click Submit in the table editor)."));
99         btnOK.addActionListener(new ActionListener() {
100                     public void actionPerformed(ActionEvent e) {
101                        setValue();
102            }});
103
104         btnEdit = new CBButton(CBIntText.get("Edit"), CBIntText.get("Edit the file data in Hex."));
105         btnEdit.addActionListener(new ActionListener() {
106                     public void actionPerformed(ActionEvent e) {
107                         setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); //TE: this could take time so set the wait cursor.
108
btnEdit.setEnabled(false); //TE: disabled to show user that they are in edit mode.
109
field.setText(bytes2HexString(bytes)); //TE: the un-shortened value (needed to edit, save etc).
110
field.setEnabled(true); //TE: so that the user can edit.
111
editHex = true; //TE: flag to show that the user is in edit mode.
112
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); //TE: sets the default cursor.
113
}});
114
115         btnCancel = new CBButton(CBIntText.get("Cancel"), CBIntText.get("Click here to exit."));
116         btnCancel.addActionListener(new ActionListener() {
117                     public void actionPerformed(ActionEvent e) {
118                        quit();
119            }});
120
121         JPanel buttonPanel = new JPanel();
122         buttonPanel.add(btnLoad);
123         buttonPanel.add(btnSave);
124
125         if (viewable)
126             buttonPanel.add(btnView);
127
128         buttonPanel.add(btnEdit);
129         buttonPanel.add(btnOK);
130         buttonPanel.add(btnCancel);
131         buttonPanel.add(addHelp()); //TE: help button for information window.
132
display.add(buttonPanel);
133
134         //TE: better way to implement keystroke listening...
135
display.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ENTER"), "enter");
136         display.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ESCAPE"), "escape");
137         display.getActionMap().put("enter", new MyAction(CBAction.ENTER));
138         display.getActionMap().put("escape", new MyAction(CBAction.ESCAPE));
139
140         getContentPane().add(display);
141         setSize(435,300);
142     }
143
144
145     /**
146      * Apparently it is better to use key bindings rather than adding a KeyListener...
147      * "for reacting in a special way to particular keys, you usually should use key
148      * bindings instead of a key listener".
149      * This class lets the user set the key as an int. If a key is pressed and it
150      * matches the assigned int, a check is done for if it is an escape or enter key.
151      * (27 or 10). If escape, the quit method is called. If enter, the setValue
152      * method is called.
153      * Bug 4646.
154      * @author Trudi.
155      */

156     private class MyAction extends CBAction
157     {
158         /**
159          * Calls super constructor.
160          * @param key
161          */

162         public MyAction(int key)
163         {
164             super(key);
165         }
166
167         /**
168          * quit is called if the Esc key pressed,
169          * setValue is called if Enter key is pressed.
170          * @param e never used.
171          */

172         public void actionPerformed(ActionEvent e)
173         {
174             if (getKey() == ESCAPE)
175                 quit();
176             else if (getKey() == ENTER)
177                 setValue();
178         }
179     }
180
181
182
183    /**
184     * Adds the text area (which is used for displaying the hex) to the panel.
185     */

186
187     public void addMainViewComponent()
188     {
189         field = new JTextArea();
190         field.setLineWrap(true); //TE: allows line wrapping.
191
field.setEnabled(false); //TE: disables the text area.
192
field.setDisabledTextColor(Color.black); //TE: sets the disabled text colour to black.
193

194         final JScrollPane scrollPane = new JScrollPane(field);
195         scrollPane.setPreferredSize(new Dimension(310,60));;
196         scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); //TE: no horizontal scroll bar.
197

198         display.makeHeavy();
199         display.addln(scrollPane);
200         display.makeLight();
201     }
202
203
204
205
206    /**
207     * Sets up the help button (which is used to open the java help at the appropriate location).
208     * @return btnHelp the button to be added.
209     */

210
211     public CBButton addHelp()
212     {
213         btnHelp = new CBButton(CBIntText.get("Help"), CBIntText.get("Click here for Help.")); //TE: creates a new help button with a listener that will open JX help at appropriate location.
214
CBHelpSystem.useDefaultHelp(btnHelp, HelpIDs.ATTR_BINARY);
215         return btnHelp;
216     }
217
218
219
220
221    /**
222     * Sets the value to display in the editor. If there is no value or if it is
223     * null, "No data available" is displayed in the editor. Otherwise the value
224     * is shortened (if needed) to 1000 characters then converted to a hex string and
225     * displayed in the text area.
226     * @param editMe a value from the dsa that is to be displayed in the editor.
227     */

228
229     public void setValue(editablebinary editMe)
230     {
231         editHex = false; //TE: hex edit flag is set to false b/c by default we set the length of the data to 1000 characters.
232

233         this.editMe = editMe;
234
235         bytes = editMe.getValue();
236
237         oldBytes = bytes; //TE: backup copy of data.
238

239         if(bytes == null || bytes.length == 0)
240             field.setText(NODATAMSG); //TE: sets the text area with "No data available".
241
else
242         {
243             setButtons(true);
244
245             byte[] shortBytes;
246             if (bytes.length < 1000)
247                 shortBytes = bytes;
248             else
249             {
250                 shortBytes = new byte[1000];
251                 System.arraycopy(bytes,0,shortBytes,0,1000);
252             }
253             field.setText(bytes2HexString(shortBytes)); //TE: sets the value of the field to a 1000 hex character string.
254
}
255     }
256
257
258
259    /**
260     * Loads binary data from file. Shortens it to 1000 characters then displays
261     * it in the binary editor.
262     */

263
264     protected void load()
265     {
266         editHex = false; //TE: hex edit flag is set to false b/c by default we set the length of the data to 1000 characters.
267

268         CBCache.cleanCache(currentDN.toString()); //TE: delete any temporary files associates with this entry.
269

270         JFileChooser chooser = new JFileChooser(JXplorer.getProperty("binary.homeDir"));
271         if (chooser.showOpenDialog(frame) != JFileChooser.APPROVE_OPTION)
272             return;
273         File file = chooser.getSelectedFile();
274         JXplorer.setProperty("binary.homeDir", chooser.getSelectedFile().getParent());
275
276         try
277         {
278             FileInputStream input = new FileInputStream(file);
279
280             int length = (int)file.length();
281             if (length > 0)
282             {
283                 setButtons(true);
284
285                 bytes = new byte[length];
286                 int read = input.read(bytes);
287
288                 byte[] shortBytes;
289                 if (bytes.length < 1000)
290                     shortBytes = bytes;
291                 else
292                 {
293                     shortBytes = new byte[1000];
294                     System.arraycopy(bytes,0,shortBytes,0,1000); //TE: copies first 1000 elements only.
295
}
296
297                 if (read > 0)
298                     field.setText(bytes2HexString(shortBytes)); //TE: converts the shortened array to a hex string then set it in the text area.
299
}
300             input.close();
301         }
302         catch(IOException e)
303         {
304             log.log(Level.WARNING, "Error opening the file!", e);
305         }
306
307     }
308
309
310
311    /**
312     * Save binary data to the file.
313     */

314
315     protected void save()
316     {
317         JFileChooser chooser = new JFileChooser();
318         if (chooser.showSaveDialog(frame) != JFileChooser.APPROVE_OPTION)
319             return;
320
321         File file = chooser.getSelectedFile();
322
323         try
324         {
325             FileOutputStream output = new FileOutputStream(file);
326             if(editHex)
327                 output.write(hexString2bytes(field.getText())); //TE: if the user is in edit mode there may be changes to the data therefore get it from the text area.
328
else
329                 output.write(bytes); //TE: the user is not in edit mode therefore no changes have been made ...'bytes' can be used.
330

331             output.close();
332         }
333         catch(IOException e)
334         {
335             log.log(Level.WARNING, "Error writing the file!", e);
336         }
337     }
338
339
340
341    /**
342     * Method purely for extending, the intention is to launch the file in
343     * its default viewer using CBLauncher.launchProgram.
344     */

345
346     public void view()
347     {
348         //TE: Extend this...odDocumentDOCEditor & odSpreadSheetXLSEditor.
349
}
350
351
352
353    /**
354     * Set the command for the binary viewer.
355     * The string must have a space at the end, as the filename will be appended.
356     */

357
358     public void setViewCommand(String JavaDoc viewCommand)
359     {
360         this.viewCommand = viewCommand;
361     }
362
363
364
365    /**
366     * Enables or disables the ok, save & edit buttons depending on the boolean value.
367     * @param enabled if true buttons are enabled, if false buttons are disabled.
368     */

369
370     public void setButtons(boolean enabled)
371     {
372         btnOK.setEnabled(enabled);
373         btnEdit.setEnabled(enabled);
374         btnSave.setEnabled(enabled);
375     }
376
377
378
379     /**
380      * Checks if the value in the editor has changed.
381      * @return true if data has changed, false if not.
382      */

383
384     public boolean isChanged()
385     {
386        if(Arrays.equals(bytes, oldBytes)==false)
387            return true;
388        return false;
389     }
390
391
392
393    /**
394     * Returns true if the current value of the attribute is valid (i.e. not null).
395     */

396
397     public boolean isValid()
398     {
399         String JavaDoc newvalue = field.getText();
400         return newvalue.length() != 0;
401     }
402
403
404
405    /**
406     * Returns a new value. If the whole file is displayed (i.e. if the user has
407     * clicked on 'edit', the new value will be retrieved from the text area. If the
408     * editor is only displaying the first 1000 characters the new value is retrieved
409     * from its source (in this case the bytes array). The idea behind this
410     * is that the only time a value can be edited/changed is when the user has clicked the
411     * edit button. Therefore this is the only time that we need to get a new value.
412     * @return byte[] a value that is to be set in the table editor.
413     */

414
415     public byte[] getNewValue()
416     {
417         if(editHex) //TE: hex edit mode flag. If it is true the new value is taken from the text area (i.e. it may have been edited).
418
{
419             String JavaDoc newvalue = field.getText();
420
421             if (newvalue!=null && newvalue.length()!=0)
422                 return hexString2bytes(newvalue);
423             else
424                 return null;
425         }
426         else
427             return bytes; //TE: the user is not in edit mode therefore no changes have been made to the bytes array.
428
}
429
430
431
432     /**
433      * This will return a structure containing the current values of the attribute.
434      * @return old value.
435      */

436
437     public byte[] getOldValue()
438     {
439         return oldBytes;
440     }
441
442
443
444    /**
445     * Sets the value in the table editor.
446     */

447
448     public void setValue()
449     {
450         if (isChanged())
451             editMe.setValue(getNewValue());
452         quit();
453     }
454
455
456
457    /**
458     * Converts a byte to hex then to a string.
459     * @param bytesForConversion value to be converted.
460     * @return string representation of hex.
461     */

462
463     public String JavaDoc bytes2HexString(byte[] bytesForConversion)
464     {
465         if (bytesForConversion!=null)
466         {
467             setEnabled(true);
468
469             hex = new StringBuffer JavaDoc(bytesForConversion.length*2);
470
471             try
472             {
473                 for (int i=0; i<bytesForConversion.length; i++)
474                 {
475                     hex.append(CBParse.byte2Hex(bytesForConversion[i]));
476                 }
477                 return hex.toString();
478             }
479             catch (Exception JavaDoc e)
480             {
481                 setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); //TE: just in case it fails and the cursor is still set to wait.
482
CBUtility.error("Problem parsing byte to hex: " + e);
483             }
484         }
485
486         setButtons(false); //TE: disables ok & edit buttons.
487

488         return NODATAMSG; //TE: set the text area to an empty string if there is no value in the directory.
489
}
490
491
492
493    /**
494     * Converts a string to hex then to a byte array.
495     * @param forConversion value to be converted.
496     * @return bytesConverted byte representation of the hex.
497     */

498
499     public byte[] hexString2bytes(String JavaDoc forConversion)
500     {
501         char charForConversion[] = forConversion.toCharArray();
502
503         byte[] bytesConverted = new byte[charForConversion.length/2];
504
505         int a = 0; //TE: loop counter.
506

507         try
508         {
509             for (int i=0;i<charForConversion.length; i=i+2) //TE: increments by two b/c two chars need to be parsed at a time.
510
{
511                 bytesConverted[a] = CBParse.hex2Byte(charForConversion[i], charForConversion[i+1]);
512                 a++;
513             }
514         }
515         catch (Exception JavaDoc e)
516         {
517             CBUtility.error("Problem parsing hex to byte: " + e);
518         }
519         return bytesConverted;
520     }
521
522
523
524    /**
525     * Shuts the window.
526     */

527
528     public void quit()
529     {
530         setVisible(false);
531         dispose();
532     }
533
534
535
536    /**
537     * Sets the dn of the entry being modified.
538     * @param dn the DN of the entry being modified.
539     *
540     */

541
542     public void setDN(DN dn)
543     {
544         currentDN = dn;
545     }
546 }
Popular Tags