KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > debug > internal > ui > views > memory > renderings > TableRenderingContentProvider


1 /*******************************************************************************
2  * Copyright (c) 2004, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.debug.internal.ui.views.memory.renderings;
13
14 import java.math.BigInteger JavaDoc;
15 import java.util.ArrayList JavaDoc;
16 import java.util.Enumeration JavaDoc;
17 import java.util.Hashtable JavaDoc;
18 import java.util.Vector JavaDoc;
19
20 import org.eclipse.debug.core.DebugEvent;
21 import org.eclipse.debug.core.DebugException;
22 import org.eclipse.debug.core.DebugPlugin;
23 import org.eclipse.debug.core.model.IDebugElement;
24 import org.eclipse.debug.core.model.IDebugTarget;
25 import org.eclipse.debug.core.model.IMemoryBlock;
26 import org.eclipse.debug.core.model.IMemoryBlockExtension;
27 import org.eclipse.debug.core.model.MemoryByte;
28 import org.eclipse.debug.internal.ui.DebugUIMessages;
29 import org.eclipse.debug.internal.ui.DebugUIPlugin;
30 import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
31 import org.eclipse.debug.internal.ui.memory.IMemoryRenderingUpdater;
32 import org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants;
33 import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil;
34 import org.eclipse.debug.ui.DebugUITools;
35 import org.eclipse.debug.ui.IDebugUIConstants;
36 import org.eclipse.debug.ui.memory.AbstractTableRendering;
37 import org.eclipse.jface.viewers.StructuredViewer;
38 import org.eclipse.jface.viewers.Viewer;
39
40 /**
41  * Content provider for MemoryViewTab
42  *
43  * @since 3.0
44  */

45 public class TableRenderingContentProvider extends BasicDebugViewContentProvider {
46     
47     // lines currently being displayed by the table rendering
48
protected Vector JavaDoc lineCache;
49     
50     // Cache to allow the content provider to comppute change information
51
// Cache is taken by copying the lineCache after a suspend event
52
// or change event from the the memory block.
53
protected Hashtable JavaDoc contentCache;
54     
55     // cache in the form of MemoryByte
56
// needed for reorganizing cache when the row size changes
57
private MemoryByte[] fContentCacheInBytes;
58     private String JavaDoc fContentCacheStartAddress;
59
60     private BigInteger JavaDoc fBufferTopAddress;
61     
62     private TableRenderingContentInput fInput;
63     private BigInteger JavaDoc fBufferEndAddress;
64     
65     private boolean fDynamicLoad;
66
67     /**
68      * @param memoryBlock
69      * @param newTab
70      */

71     public TableRenderingContentProvider()
72     {
73         lineCache = new Vector JavaDoc();
74         contentCache = new Hashtable JavaDoc();
75         initializeDynamicLoad();
76             
77         DebugPlugin.getDefault().addDebugEventListener(this);
78     }
79     
80     /**
81      * @param viewer
82      */

83     public void setViewer(StructuredViewer viewer)
84     {
85         fViewer = viewer;
86     }
87     
88     /* (non-Javadoc)
89      * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
90      */

91     public void inputChanged(Viewer v, Object JavaDoc oldInput, Object JavaDoc newInput) {
92         try {
93             if (newInput instanceof TableRenderingContentInput)
94             {
95                 fInput = (TableRenderingContentInput)newInput;
96                 if (fInput.getMemoryBlock() instanceof IMemoryBlockExtension)
97                     loadContentForExtendedMemoryBlock();
98                 else
99                     loadContentForSimpleMemoryBlock();
100                 
101                 // tell rendering to display table if the loading is successful
102
getTableRendering(fInput).displayTable();
103             }
104         } catch (DebugException e) {
105             getTableRendering(fInput).displayError(e);
106         }
107     }
108
109     public void dispose() {
110         DebugPlugin.getDefault().removeDebugEventListener(this);
111         super.dispose();
112     }
113
114     /* (non-Javadoc)
115      * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
116      */

117     public Object JavaDoc[] getElements(Object JavaDoc parent) {
118
119         // if cache is empty, get memory
120
if (lineCache.isEmpty()) {
121         
122             try {
123                 getMemoryFromMemoryBlock();
124             } catch (DebugException e) {
125                 DebugUIPlugin.log(e.getStatus());
126                 getTableRendering(fInput).displayError(e);
127                 return lineCache.toArray();
128             }
129         }
130         
131         if (lineCache.isEmpty())
132             return lineCache.toArray();
133         
134         // check to see if the row size has changed
135
TableRenderingLine line = (TableRenderingLine)lineCache.get(0);
136         int currentRowSize = line.getByteArray().length;
137         int renderingRowSize = getTableRendering(fInput).getBytesPerLine();
138         
139         if (renderingRowSize != currentRowSize)
140         {
141             try {
142                 reorganizeContentCache(renderingRowSize);
143                 reorganizeLines(lineCache, renderingRowSize);
144             } catch (DebugException e) {
145                 DebugUIPlugin.log(e.getStatus());
146                 getTableRendering(fInput).displayError(e);
147                 return lineCache.toArray();
148             }
149         }
150         return lineCache.toArray();
151     }
152     
153     private void getMemoryFromMemoryBlock() throws DebugException {
154         IMemoryBlock memoryBlock = fInput.getMemoryBlock();
155         if (memoryBlock instanceof IMemoryBlockExtension)
156         {
157             loadContentForExtendedMemoryBlock();
158             getTableRendering(fInput).displayTable();
159         }
160         else
161         {
162             loadContentForSimpleMemoryBlock();
163             getTableRendering(fInput).displayTable();
164         }
165     }
166
167     /**
168      * @throws DebugException
169      */

170     public void loadContentForSimpleMemoryBlock() throws DebugException {
171         // get as much memory as the memory block can handle
172
fInput.setPreBuffer(0);
173         fInput.setPostBuffer(0);
174         long startAddress = fInput.getMemoryBlock().getStartAddress();
175         BigInteger JavaDoc address = BigInteger.valueOf(startAddress);
176         long length = fInput.getMemoryBlock().getLength();
177         long numLines = length / getTableRendering(fInput).getBytesPerLine();
178         getMemoryToFitTable(address, numLines, fInput.isUpdateDelta());
179     }
180
181     /**
182      * @throws DebugException
183      */

184     public void loadContentForExtendedMemoryBlock() throws DebugException {
185         
186         // do not load if number of lines needed is < 0
187
if (fInput.getNumLines() <= 0)
188             return;
189         
190         // calculate top buffered address
191
BigInteger JavaDoc loadAddress = fInput.getLoadAddress();
192         if (loadAddress == null)
193         {
194             loadAddress = new BigInteger JavaDoc("0"); //$NON-NLS-1$
195
}
196         
197         BigInteger JavaDoc mbStart = fInput.getStartAddress();
198         BigInteger JavaDoc mbEnd = fInput.getEndAddress();
199         
200         // check that the load address is within range
201
if (loadAddress.compareTo(mbStart) < 0 || loadAddress.compareTo(mbEnd) > 0)
202         {
203             // default load address to memory block base address
204
loadAddress = ((IMemoryBlockExtension)getMemoryBlock()).getBigBaseAddress();
205             fInput.setLoadAddress(loadAddress);
206         }
207         
208         // if address is still out of range, throw an exception
209
if (loadAddress.compareTo(mbStart) < 0 || loadAddress.compareTo(mbEnd) > 0)
210         {
211             throw new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.TableRenderingContentProvider_0 + loadAddress.toString(16), null));
212         }
213         
214         int addressableUnitsPerLine = getTableRendering(fInput).getAddressableUnitPerLine();
215         BigInteger JavaDoc bufferStart = loadAddress.subtract(BigInteger.valueOf(fInput.getPreBuffer()*addressableUnitsPerLine));
216         BigInteger JavaDoc bufferEnd = loadAddress.add(BigInteger.valueOf(fInput.getPostBuffer()*addressableUnitsPerLine));
217         bufferEnd = bufferEnd.add(BigInteger.valueOf(fInput.getNumLines()*addressableUnitsPerLine));
218         
219         if (isDynamicLoad())
220         {
221             if (bufferStart.compareTo(mbStart) < 0)
222                 bufferStart = mbStart;
223             
224             if (bufferEnd.compareTo(mbEnd) > 0)
225             {
226                 bufferEnd = mbEnd;
227                 
228                 int numLines = bufferEnd.subtract(bufferStart).divide(BigInteger.valueOf(addressableUnitsPerLine)).intValue();
229                 if (numLines < fInput.getNumLines())
230                 {
231                     // re-calculate buffer start since we may not have enough lines to popoulate the view
232
bufferStart = bufferEnd.subtract(BigInteger.valueOf(fInput.getNumLines()*addressableUnitsPerLine));
233                     bufferStart = bufferStart.subtract(BigInteger.valueOf(fInput.getPreBuffer()*addressableUnitsPerLine));
234                 }
235             }
236             
237             // buffer end must be greater than buffer start
238
if (bufferEnd.compareTo(bufferStart) <= 0)
239                 throw new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.TableRenderingContentProvider_1, null));
240             
241             int numLines = bufferEnd.subtract(bufferStart).divide(BigInteger.valueOf(addressableUnitsPerLine)).intValue()+1;
242             // get stoarage to fit the memory view tab size
243
getMemoryToFitTable(bufferStart, numLines, fInput.isUpdateDelta());
244         }
245         else
246         {
247             if (bufferStart.compareTo(mbStart) < 0)
248                 bufferStart = mbStart;
249             
250             if (bufferEnd.compareTo(mbEnd) > 0)
251             {
252                 bufferStart = mbEnd.subtract(BigInteger.valueOf((fInput.getNumLines()-1)*addressableUnitsPerLine));
253             }
254             
255             // buffer end must be greater than buffer start
256
if (bufferEnd.compareTo(bufferStart) <= 0)
257                 throw new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.TableRenderingContentProvider_2, null));
258             
259             int numLines = fInput.getNumLines();
260             // get stoarage to fit the memory view tab size
261
getMemoryToFitTable(bufferStart, numLines, fInput.isUpdateDelta());
262         }
263     }
264     
265     /**
266      * @return the memroy block
267      */

268     public IMemoryBlock getMemoryBlock() {
269         return fInput.getMemoryBlock();
270     }
271     
272     /**
273      * Get memory to fit table
274      * @param startingAddress
275      * @param numberOfLines
276      * @param updateDelta
277      * @throws DebugException
278      */

279     public void getMemoryToFitTable(BigInteger JavaDoc startingAddress, long numberOfLines, boolean updateDelta) throws DebugException
280     {
281         // do not ask for memory from memory block if the debug target
282
// is already terminated
283
IDebugTarget target = fInput.getMemoryBlock().getDebugTarget();
284         
285         if (target.isDisconnected() || target.isTerminated())
286             return;
287         
288         boolean error = false;
289         DebugException dbgEvt = null;
290         
291         // calculate address size
292
String JavaDoc adjustedAddress = startingAddress.toString(16);
293         
294         int addressSize;
295         try {
296             addressSize = getAddressSize(startingAddress);
297         } catch (DebugException e1) {
298             dbgEvt = e1;
299             error = true;
300             addressSize = 4;
301         }
302         
303         int addressLength = addressSize * IInternalDebugUIConstants.CHAR_PER_BYTE;
304
305         // align to the closest boundary based on addressable size per line
306
if ( getMemoryBlock() instanceof IMemoryBlockExtension)
307         {
308             startingAddress = MemoryViewUtil.alignToBoundary(startingAddress, getTableRendering(fInput).getAddressableUnitPerLine());
309         }
310
311         IMemoryBlockExtension extMemoryBlock = null;
312         MemoryByte[] memoryBuffer = null;
313         
314         String JavaDoc paddedString = DebugUIPlugin.getDefault().getPreferenceStore().getString(IDebugUIConstants.PREF_PADDED_STR);
315         
316         long reqNumBytes = 0;
317         try
318         {
319             if (fInput.getMemoryBlock() instanceof IMemoryBlockExtension)
320             {
321                 reqNumBytes = getTableRendering(fInput).getBytesPerLine() * numberOfLines;
322                 // get memory from memory block
323
extMemoryBlock = (IMemoryBlockExtension) fInput.getMemoryBlock();
324                 
325                 long reqNumberOfUnits = getTableRendering(fInput).getAddressableUnitPerLine() * numberOfLines;
326                         
327                 memoryBuffer = extMemoryBlock.getBytesFromAddress(startingAddress, reqNumberOfUnits);
328         
329                 if(memoryBuffer == null)
330                 {
331                     DebugException e = new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.MemoryViewContentProvider_Unable_to_retrieve_content, null));
332                     throw e;
333                 }
334             }
335             else
336             {
337                 // get memory from memory block
338
byte[] memory = fInput.getMemoryBlock().getBytes();
339                 
340                 if (memory == null)
341                 {
342                     DebugException e = new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.MemoryViewContentProvider_Unable_to_retrieve_content, null));
343                     throw e;
344                 }
345                 
346                 int prefillNumBytes = 0;
347                 
348                 // number of bytes need to prefill
349
if (!startingAddress.toString(16).endsWith("0")) //$NON-NLS-1$
350
{
351                     adjustedAddress = startingAddress.toString(16).substring(0, adjustedAddress.length() - 1);
352                     adjustedAddress += "0"; //$NON-NLS-1$
353
BigInteger JavaDoc adjustedStart = new BigInteger JavaDoc(adjustedAddress, 16);
354                     prefillNumBytes = startingAddress.subtract(adjustedStart).intValue();
355                     startingAddress = adjustedStart;
356                 }
357                 reqNumBytes = fInput.getMemoryBlock().getLength() + prefillNumBytes;
358                 
359                 // figure out number of dummy bytes to append
360
while (reqNumBytes % getTableRendering(fInput).getBytesPerLine() != 0)
361                 {
362                     reqNumBytes ++;
363                 }
364                 
365                 numberOfLines = reqNumBytes / getTableRendering(fInput).getBytesPerLine();
366                 
367                 // create memory byte for IMemoryBlock
368
memoryBuffer = new MemoryByte[(int)reqNumBytes];
369                 
370                 // prefill buffer to ensure double-word alignment
371
for (int i=0; i<prefillNumBytes; i++)
372                 {
373                     MemoryByte tmp = new MemoryByte();
374                     tmp.setValue((byte)0);
375                     tmp.setWritable(false);
376                     tmp.setReadable(false);
377                     tmp.setEndianessKnown(false);
378                     memoryBuffer[i] = tmp;
379                 }
380                 
381                 // fill buffer with memory returned by debug adapter
382
int j = prefillNumBytes; // counter for memoryBuffer
383
for (int i=0; i<memory.length; i++)
384                 {
385                     MemoryByte tmp = new MemoryByte();
386                     tmp.setValue(memory[i]);
387                     tmp.setReadable(true);
388                     tmp.setWritable(true);
389                     tmp.setEndianessKnown(false);
390                     memoryBuffer[j] = tmp;
391                     j++;
392                 }
393                 
394                 // append to buffer to fill up the entire line
395
for (int i=j; i<memoryBuffer.length; i++)
396                 {
397                     MemoryByte tmp = new MemoryByte();
398                     tmp.setValue((byte)0);
399                     tmp.setWritable(false);
400                     tmp.setReadable(false);
401                     tmp.setEndianessKnown(false);
402                     memoryBuffer[i] = tmp;
403                 }
404             }
405         }
406         catch (DebugException e)
407         {
408             memoryBuffer = makeDummyContent(numberOfLines);
409             
410             // finish creating the content provider before throwing an event
411
error = true;
412             dbgEvt = e;
413         }
414         catch (Throwable JavaDoc e)
415         {
416             // catch all errors from this process just to be safe
417
memoryBuffer = makeDummyContent(numberOfLines);
418             
419             // finish creating the content provider before throwing an event
420
error = true;
421             dbgEvt = new DebugException(DebugUIPlugin.newErrorStatus(e.getMessage(), e));
422         }
423         
424         // if debug adapter did not return enough memory, create dummy memory
425
if (memoryBuffer.length < reqNumBytes)
426         {
427             ArrayList JavaDoc newBuffer = new ArrayList JavaDoc();
428             
429             for (int i=0; i<memoryBuffer.length; i++)
430             {
431                 newBuffer.add(memoryBuffer[i]);
432             }
433             
434             for (int i=memoryBuffer.length; i<reqNumBytes; i++)
435             {
436                 MemoryByte mb = new MemoryByte();
437                 mb.setReadable(false);
438                 mb.setWritable(false);
439                 mb.setEndianessKnown(false);
440                 newBuffer.add(mb);
441             }
442             
443             memoryBuffer = (MemoryByte[])newBuffer.toArray(new MemoryByte[newBuffer.size()]);
444             
445         }
446         
447         // clear line cache
448
if (!lineCache.isEmpty())
449         {
450             lineCache.clear();
451         }
452         String JavaDoc address = startingAddress.toString(16);
453         // save address of the top of buffer
454
fBufferTopAddress = startingAddress;
455         
456         boolean manageDelta = true;
457         
458         // If change information is not managed by the memory block
459
// The view tab will manage it and calculate delta information
460
// for its content cache.
461
if (fInput.getMemoryBlock() instanceof IMemoryBlockExtension)
462         {
463             manageDelta = !((IMemoryBlockExtension)fInput.getMemoryBlock()).supportsChangeManagement();
464         }
465             
466         // put memory information into MemoryViewLine
467
organizeLines(numberOfLines, updateDelta, addressLength, memoryBuffer, paddedString, address, manageDelta);
468         
469         if (error){
470             throw dbgEvt;
471         }
472     }
473
474     private void organizeLines(long numberOfLines, boolean updateDelta, int addressLength, MemoryByte[] memoryBuffer, String JavaDoc paddedString, String JavaDoc address, boolean manageDelta)
475     {
476         for (int i = 0; i < numberOfLines; i++)
477         { //chop the raw memory up
478
String JavaDoc tmpAddress = address.toUpperCase();
479             if (tmpAddress.length() < addressLength)
480             {
481                 for (int j = 0; tmpAddress.length() < addressLength; j++)
482                 {
483                     tmpAddress = "0" + tmpAddress; //$NON-NLS-1$
484
}
485             }
486             int bytesPerLine = getTableRendering(fInput).getBytesPerLine();
487             MemoryByte[] memory = new MemoryByte[bytesPerLine];
488             boolean isMonitored = true;
489             
490             // counter for memory, starts from 0 to number of bytes per line
491
int k = 0;
492             // j is the counter for memArray, memory returned by debug adapter
493
for (int j = i * bytesPerLine;
494                 j < i * bytesPerLine + bytesPerLine;
495                 j++)
496             {
497                 
498                 byte changeFlag = memoryBuffer[j].getFlags();
499                 if (manageDelta)
500                 {
501                     // turn off both change and known bits to make sure that
502
// the change bits returned by debug adapters do not take
503
// any effect
504

505                     changeFlag |= MemoryByte.HISTORY_KNOWN;
506                     changeFlag ^= MemoryByte.HISTORY_KNOWN;
507                     
508                     changeFlag |= MemoryByte.CHANGED;
509                     changeFlag ^= MemoryByte.CHANGED;
510                 }
511                 
512                 MemoryByte newByteObj = new MemoryByte(memoryBuffer[j].getValue(), changeFlag);
513                 memory[k] = newByteObj;
514                 k++;
515                 
516                 
517                 if (!manageDelta)
518                 {
519                     // If the byte is marked as unknown, the line is not monitored
520
if (!memoryBuffer[j].isHistoryKnown())
521                     {
522                         isMonitored = false;
523                     }
524                 }
525             }
526             
527             TableRenderingLine newLine = new TableRenderingLine(tmpAddress, memory, lineCache.size(), paddedString);
528             
529             TableRenderingLine oldLine = (TableRenderingLine)contentCache.get(newLine.getAddress());
530             
531             if (manageDelta)
532             {
533                 if (oldLine != null)
534                     newLine.isMonitored = true;
535                 else
536                     newLine.isMonitored = false;
537             }
538             else
539             {
540                 // check the byte for information
541
newLine.isMonitored = isMonitored;
542             }
543             
544             // calculate delta info for the memory view line
545
if (manageDelta && !getTableRendering(fInput).isDisplayingError())
546             {
547                 if (updateDelta)
548                 {
549                     if (oldLine != null)
550                     {
551                         newLine.markDeltas(oldLine);
552                     }
553                 }
554                 else
555                 {
556                     if (oldLine != null)
557                     {
558                         // deltas can only be reused if the line has not been changed
559
// otherwise, force a refresh
560
if (newLine.isLineChanged(oldLine))
561                         {
562                             newLine.markDeltas(oldLine);
563                         }
564                         else
565                         {
566                             newLine.copyDeltas(oldLine);
567                         }
568                     }
569                 }
570             }
571             else if (manageDelta && getTableRendering(fInput).isDisplayingError())
572             {
573                 // show as unmonitored if the view tab is previoulsy displaying error
574
newLine.isMonitored = false;
575             }
576             lineCache.add(newLine);
577             
578             
579             // increment row address
580
BigInteger JavaDoc bigInt = new BigInteger JavaDoc(address, 16);
581             fBufferEndAddress = bigInt;
582             int addressableUnit = getTableRendering(fInput).getBytesPerLine()/getTableRendering(fInput).getAddressableSize();
583             address = bigInt.add(BigInteger.valueOf(addressableUnit)).toString(16);
584         }
585     }
586     
587     /**
588      * @param numberOfLines
589      * @return an array of dummy MemoryByte
590      */

591     private MemoryByte[] makeDummyContent(long numberOfLines) {
592         MemoryByte[] memoryBuffer;
593         // make up dummy memory, needed for recovery in case the debug adapter
594
// is capable of retrieving memory again
595

596         int numBytes = (int)(getTableRendering(fInput).getBytesPerLine() * numberOfLines);
597         memoryBuffer = new MemoryByte[numBytes];
598         
599         for (int i=0; i<memoryBuffer.length; i++){
600             memoryBuffer[i] = new MemoryByte();
601             memoryBuffer[i].setValue((byte)0);
602             memoryBuffer[i].setWritable(false);
603             memoryBuffer[i].setReadable(false);
604             memoryBuffer[i].setEndianessKnown(false);
605         }
606         return memoryBuffer;
607     }
608
609     /* (non-Javadoc)
610      * @see org.eclipse.debug.ui.internal.views.BasicDebugViewContentProvider#doHandleDebugEvent(org.eclipse.debug.core.DebugEvent)
611      */

612     protected void doHandleDebugEvent(DebugEvent event) {
613         
614         if (getTableRendering(fInput).isVisible())
615         {
616             // only do this if it's visible
617
// still need to clear content cache if the rendering
618
// is not visible
619
if (isUpdateManagedByMB())
620                 return;
621         }
622         
623         // do nothing if the debug event did not come from a debug element comes from non-debug element
624
if (!(event.getSource() instanceof IDebugElement))
625             return;
626         
627         // do not try to recover if the content input has not been created
628
if (fInput == null)
629             return;
630         
631         IDebugElement src = (IDebugElement)event.getSource();
632         
633         // if a debug event happens from the memory block
634
// invoke contentChanged to get content of the memory block updated
635
if (event.getKind() == DebugEvent.CHANGE && event.getSource() == fInput.getMemoryBlock())
636         {
637             if (event.getDetail() == DebugEvent.STATE){
638                 getTableRendering(fInput).updateLabels();
639             }
640             else
641             {
642                 updateContent();
643             }
644         }
645         
646         // if the suspend evnet happens from the debug target that the
647
// memory block belongs to
648
if (event.getKind() == DebugEvent.SUSPEND && src.getDebugTarget() == fInput.getMemoryBlock().getDebugTarget())
649         {
650             updateContent();
651         }
652
653     }
654     
655     /**
656      * Update content of the view tab if the content of the memory block has changed
657      * or if its base address has changed
658      * Update will not be performed if the memory block has not been changed or
659      * if the rendering is not visible
660      */

661     public void updateContent()
662     {
663         IDebugTarget dt = fInput.getMemoryBlock().getDebugTarget();
664         
665         // no need to update if debug target is disconnected or terminated
666
if (dt.isDisconnected() || dt.isTerminated())
667         {
668             return;
669         }
670         
671         takeContentSnapshot();
672         
673         //do not handle event if the rendering is not visible
674
if (!getTableRendering(fInput).isVisible())
675              return;
676         
677         getTableRendering(fInput).refresh();
678         
679     }
680     
681     /**
682      * Take a snapshot on the content, marking the lines as monitored
683      */

684     public void takeContentSnapshot()
685     {
686         // cache content before getting new ones
687
TableRenderingLine[] lines =(TableRenderingLine[]) lineCache.toArray(new TableRenderingLine[lineCache.size()]);
688         fContentCacheInBytes = convertLinesToBytes(lines);
689         fContentCacheStartAddress = lines[0].getAddress();
690         
691         if (contentCache != null)
692         {
693             contentCache.clear();
694         }
695         
696         //do not handle event if the rendering is not visible
697
if (!getTableRendering(fInput).isVisible())
698              return;
699         
700         // use existing lines as cache is the rendering is not currently displaying
701
// error. Otherwise, leave contentCache empty as we do not have updated
702
// content.
703
if (!getTableRendering(fInput).isDisplayingError())
704         {
705             for (int i=0; i<lines.length; i++)
706             {
707                 contentCache.put(lines[i].getAddress(), lines[i]);
708                 lines[i].isMonitored = true;
709             }
710         }
711
712         // reset all the deltas currently stored in contentCache
713
// This will ensure that changes will be recomputed when user scrolls
714
// up or down the memory view.
715
resetDeltas();
716     }
717
718     /**
719      * @return buffer's top address
720      */

721     public BigInteger JavaDoc getBufferTopAddress()
722     {
723         return fBufferTopAddress;
724     }
725     
726     public BigInteger JavaDoc getBufferEndAddress()
727     {
728         return fBufferEndAddress;
729     }
730     
731     /**
732      * Calculate address size of the given address
733      * @param address
734      * @return size of address from the debuggee
735      */

736     public int getAddressSize(BigInteger JavaDoc address) throws DebugException
737     {
738         // calculate address size
739
String JavaDoc adjustedAddress = address.toString(16);
740         
741          int addressSize = 0;
742          if (fInput.getMemoryBlock() instanceof IMemoryBlockExtension)
743          {
744              addressSize = ((IMemoryBlockExtension)fInput.getMemoryBlock()).getAddressSize();
745          }
746         
747          // handle IMemoryBlock and invalid address size returned by IMemoryBlockExtension
748
if (addressSize <= 0)
749          {
750              if (adjustedAddress.length() > 8)
751              {
752                  addressSize = 8;
753              }
754              else
755              {
756                  addressSize = 4;
757              }
758          }
759          
760          return addressSize;
761     }
762     
763     /**
764      * @return base address of memory block
765      */

766     public BigInteger JavaDoc getContentBaseAddress()
767     {
768         return fInput.getContentBaseAddress();
769     }
770     
771     /**
772      * Clear all delta information in the lines
773      */

774     public void resetDeltas()
775     {
776         Enumeration JavaDoc enumeration = contentCache.elements();
777         
778         while (enumeration.hasMoreElements())
779         {
780             TableRenderingLine line = (TableRenderingLine)enumeration.nextElement();
781             line.unmarkDeltas();
782         }
783     }
784     
785     /**
786      * Check if address is out of buffered range
787      * @param address
788      * @return true if address is out of bufferred range, false otherwise
789      */

790     public boolean isAddressOutOfRange(BigInteger JavaDoc address)
791     {
792         if (lineCache != null && !lineCache.isEmpty())
793         {
794             TableRenderingLine first = (TableRenderingLine)lineCache.firstElement();
795             TableRenderingLine last = (TableRenderingLine) lineCache.lastElement();
796             
797             if (first == null ||last == null)
798                 return true;
799             
800             BigInteger JavaDoc startAddress = new BigInteger JavaDoc(first.getAddress(), 16);
801             BigInteger JavaDoc lastAddress = new BigInteger JavaDoc(last.getAddress(), 16);
802             int addressableUnit = getTableRendering(fInput).getAddressableUnitPerLine();
803             lastAddress = lastAddress.add(BigInteger.valueOf(addressableUnit)).subtract(BigInteger.valueOf(1));
804             
805             if (startAddress.compareTo(address) <= 0 &&
806                 lastAddress.compareTo(address) >= 0)
807             {
808                 return false;
809             }
810             return true;
811         }
812         return true;
813     }
814     
815     public void clearContentCache()
816     {
817         fContentCacheInBytes = new MemoryByte[0];
818         fContentCacheStartAddress = null;
819         contentCache.clear();
820     }
821     
822     /**
823      * @return if the memory block would manage its own update.
824      */

825     private boolean isUpdateManagedByMB()
826     {
827         IMemoryBlock memoryBlock = getMemoryBlock();
828         
829         IMemoryRenderingUpdater managedMB = null;
830         if (memoryBlock instanceof IMemoryRenderingUpdater)
831         {
832             managedMB = (IMemoryRenderingUpdater)memoryBlock;
833         }
834         
835         if (managedMB == null)
836             managedMB = (IMemoryRenderingUpdater)memoryBlock.getAdapter(IMemoryRenderingUpdater.class);
837         
838         // do not handle event if if the memory block wants to do its
839
// own update
840
if (managedMB != null && managedMB.supportsManagedUpdate(getTableRendering(fInput)))
841             return true;
842         
843         return false;
844     }
845     
846     public boolean isDynamicLoad()
847     {
848         return fDynamicLoad;
849     }
850     
851     private void initializeDynamicLoad()
852     {
853         fDynamicLoad = DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugPreferenceConstants.PREF_DYNAMIC_LOAD_MEM);
854     }
855     
856     public void setDynamicLoad(boolean dynamicLoad)
857     {
858         fDynamicLoad = dynamicLoad;
859     }
860     
861     private void reorganizeLines(Vector JavaDoc lines, int numBytesPerLine) throws DebugException
862     {
863         if (lines == null || lines.isEmpty())
864             return;
865         
866         Object JavaDoc[] objs = lines.toArray();
867         
868         if (objs.length > 0)
869         {
870             TableRenderingLine[] renderingLines = (TableRenderingLine[])lines.toArray(new TableRenderingLine[lines.size()]);
871             MemoryByte[] buffer = convertLinesToBytes(renderingLines);
872             BigInteger JavaDoc lineAddress = new BigInteger JavaDoc(renderingLines[0].getAddress(), 16);
873             int numberOfLines = buffer.length / numBytesPerLine;
874             boolean updateDelta = false;
875             int addressLength = getAddressSize(lineAddress) * IInternalDebugUIConstants.CHAR_PER_BYTE;
876             MemoryByte[] memoryBuffer = buffer;
877             String JavaDoc address =renderingLines[0].getAddress();
878             String JavaDoc paddedString = DebugUITools.getPreferenceStore().getString(IDebugUIConstants.PREF_PADDED_STR);
879             
880             // set to false to preserve information delta information
881
boolean manageDelta = true;
882             
883             // If change information is not managed by the memory block
884
// The view tab will manage it and calculate delta information
885
// for its content cache.
886
if (fInput.getMemoryBlock() instanceof IMemoryBlockExtension)
887             {
888                 manageDelta = !((IMemoryBlockExtension)fInput.getMemoryBlock()).supportsChangeManagement();
889             }
890             lineCache.clear();
891             
892             organizeLines(numberOfLines, updateDelta, addressLength, memoryBuffer, paddedString, address, manageDelta);
893         }
894     }
895     
896     private void reorganizeContentCache(int bytesPerLine)
897     {
898         // if content cache is empty, do nothing
899
if (contentCache == null || contentCache.isEmpty()
900             || fContentCacheInBytes.length == 0 || fContentCacheStartAddress == null)
901             return;
902         
903         MemoryByte[] bytes = fContentCacheInBytes;
904         TableRenderingLine[] convertedLines = convertBytesToLines(bytes, bytesPerLine, new BigInteger JavaDoc(fContentCacheStartAddress, 16));
905         
906         contentCache.clear();
907         for (int i=0; i<convertedLines.length; i++)
908         {
909             contentCache.put(convertedLines[i].getAddress(), convertedLines[i]);
910         }
911     }
912     
913     private MemoryByte[] convertLinesToBytes(TableRenderingLine[] lines)
914     {
915         // convert the lines back to a buffer of MemoryByte
916
TableRenderingLine temp = lines[0];
917         int lineLength = temp.getLength();
918
919         MemoryByte[] buffer = new MemoryByte[lines.length * lineLength];
920         for (int i=0; i<lines.length; i++)
921         {
922             TableRenderingLine line = lines[i];
923             MemoryByte[] bytes = line.getBytes();
924             System.arraycopy(bytes, 0, buffer, i*lineLength, lineLength);
925         }
926         return buffer;
927     }
928     
929     private TableRenderingLine[] convertBytesToLines(MemoryByte[] bytes, int bytesPerLine, BigInteger JavaDoc startAddress)
930     {
931         int numOfLines = bytes.length / bytesPerLine;
932         String JavaDoc address = startAddress.toString(16);
933         int addressLength;
934         try {
935             addressLength = getAddressSize(startAddress) * IInternalDebugUIConstants.CHAR_PER_BYTE;
936         } catch (DebugException e) {
937             DebugUIPlugin.log(e);
938             addressLength = 4 * IInternalDebugUIConstants.CHAR_PER_BYTE;
939         }
940         ArrayList JavaDoc lines = new ArrayList JavaDoc();
941         String JavaDoc paddedString = DebugUITools.getPreferenceStore().getString(IDebugUIConstants.PREF_PADDED_STR);
942         
943         for (int i=0; i<numOfLines; i++)
944         {
945             MemoryByte[] temp = new MemoryByte[bytesPerLine];
946             System.arraycopy(bytes, i*bytesPerLine, temp, 0, bytesPerLine);
947             
948             String JavaDoc tmpAddress = address.toUpperCase();
949             if (tmpAddress.length() < addressLength)
950             {
951                 for (int j = 0; tmpAddress.length() < addressLength; j++)
952                 {
953                     tmpAddress = "0" + tmpAddress; //$NON-NLS-1$
954
}
955             }
956             
957             TableRenderingLine newLine = new TableRenderingLine(tmpAddress, temp, lines.size(), paddedString);
958             lines.add(newLine);
959             
960             // increment row address
961
BigInteger JavaDoc bigInt = new BigInteger JavaDoc(address, 16);
962             fBufferEndAddress = bigInt;
963             int addressableUnit = getTableRendering(fInput).getBytesPerLine()/getTableRendering(fInput).getAddressableSize();
964             address = bigInt.add(BigInteger.valueOf(addressableUnit)).toString(16);
965         }
966         
967         return (TableRenderingLine[])lines.toArray(new TableRenderingLine[lines.size()]);
968     }
969     
970     private AbstractTableRendering getTableRendering(TableRenderingContentInput input)
971     {
972         return (AbstractTableRendering)input.getAdapter(AbstractTableRendering.class);
973     }
974 }
975
Popular Tags