KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > debug > internal > ui > elements > adapters > MemoryBlockContentAdapter


1 /*******************************************************************************
2  * Copyright (c) 2006, 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.elements.adapters;
13
14 import java.math.BigInteger JavaDoc;
15 import java.util.ArrayList JavaDoc;
16 import java.util.Hashtable JavaDoc;
17 import java.util.Vector JavaDoc;
18
19 import org.eclipse.core.runtime.CoreException;
20 import org.eclipse.debug.core.DebugException;
21 import org.eclipse.debug.core.model.IDebugTarget;
22 import org.eclipse.debug.core.model.IMemoryBlock;
23 import org.eclipse.debug.core.model.IMemoryBlockExtension;
24 import org.eclipse.debug.core.model.MemoryByte;
25 import org.eclipse.debug.internal.ui.DebugUIMessages;
26 import org.eclipse.debug.internal.ui.DebugUIPlugin;
27 import org.eclipse.debug.internal.ui.memory.provisional.AbstractAsyncTableRendering;
28 import org.eclipse.debug.internal.ui.memory.provisional.MemoryViewPresentationContext;
29 import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
30 import org.eclipse.debug.internal.ui.viewers.provisional.AsynchronousContentAdapter;
31 import org.eclipse.debug.internal.ui.views.memory.MemoryViewUtil;
32 import org.eclipse.debug.internal.ui.views.memory.renderings.MemorySegment;
33 import org.eclipse.debug.internal.ui.views.memory.renderings.TableRenderingContentDescriptor;
34 import org.eclipse.debug.ui.memory.IMemoryRendering;
35
36 public class MemoryBlockContentAdapter extends AsynchronousContentAdapter {
37
38     // Cache to allow the content provider to comppute change information
39
// Cache is taken by copying the lineCache after a suspend event
40
// or change event from the the memory block.
41
protected Hashtable JavaDoc contentCache;
42     
43     public MemoryBlockContentAdapter()
44     {
45         contentCache = new Hashtable JavaDoc();
46     }
47
48     protected Object JavaDoc[] getChildren(Object JavaDoc parent, IPresentationContext context)
49             throws CoreException {
50         
51         if (!(parent instanceof IMemoryBlock))
52             return new Object JavaDoc[0];
53         
54         if (!(context instanceof MemoryViewPresentationContext))
55             return new Object JavaDoc[0];
56         
57         MemoryViewPresentationContext memoryViewContext = (MemoryViewPresentationContext)context;
58         IMemoryRendering rendering = memoryViewContext.getRendering();
59         
60         if (!(rendering instanceof AbstractAsyncTableRendering))
61             return new Object JavaDoc[0];
62             
63         try
64         {
65             return getMemoryFromMemoryBlock(memoryViewContext);
66         } catch (DebugException e) {
67             throw e;
68         }
69
70     }
71
72     protected boolean hasChildren(Object JavaDoc element, IPresentationContext context)
73             throws CoreException {
74         
75         if (context instanceof MemoryViewPresentationContext)
76         {
77             if (((MemoryViewPresentationContext)context).getRendering() != null)
78                 return true;
79         }
80         
81         return false;
82     }
83
84     protected boolean supportsPartId(String JavaDoc id) {
85         return true;
86     }
87     
88     
89     private Object JavaDoc[] getMemoryFromMemoryBlock(MemoryViewPresentationContext context) throws DebugException {
90         IMemoryBlock memoryBlock = context.getRendering().getMemoryBlock();
91         if (memoryBlock instanceof IMemoryBlockExtension)
92         {
93             return loadContentForExtendedMemoryBlock(context);
94         }
95
96         return loadContentForSimpleMemoryBlock(context);
97         
98     }
99
100     /**
101      * @throws DebugException
102      */

103     public Object JavaDoc[] loadContentForSimpleMemoryBlock(MemoryViewPresentationContext context) throws DebugException {
104         AbstractAsyncTableRendering rendering = getTableRendering(context);
105         if (rendering != null)
106         {
107             IMemoryBlock memoryBlock = rendering.getMemoryBlock();
108             long startAddress = memoryBlock.getStartAddress();
109             BigInteger JavaDoc address = BigInteger.valueOf(startAddress);
110             long length = memoryBlock.getLength();
111             long numLines = length / rendering.getBytesPerLine();
112             return getMemoryToFitTable(address, numLines, context);
113         }
114         return EMPTY;
115     }
116
117     /**
118      * @throws DebugException
119      */

120     public Object JavaDoc[] loadContentForExtendedMemoryBlock(MemoryViewPresentationContext context) throws DebugException {
121         
122         AbstractAsyncTableRendering rendering = getTableRendering(context);
123         if (rendering != null)
124         {
125             TableRenderingContentDescriptor descriptor = (TableRenderingContentDescriptor)rendering.getAdapter(TableRenderingContentDescriptor.class);
126             
127             if (descriptor == null)
128                 return new Object JavaDoc[0];
129             
130             if (descriptor.getNumLines() <= 0)
131                 return new Object JavaDoc[0];
132             
133             // calculate top buffered address
134
BigInteger JavaDoc loadAddress = descriptor.getLoadAddress();
135             if (loadAddress == null)
136             {
137                 loadAddress = new BigInteger JavaDoc("0"); //$NON-NLS-1$
138
}
139             
140             BigInteger JavaDoc mbStart = descriptor.getStartAddress();
141             BigInteger JavaDoc mbEnd = descriptor.getEndAddress();
142             
143             // check that the load address is within range
144
if (loadAddress.compareTo(mbStart) < 0 || loadAddress.compareTo(mbEnd) > 0)
145             {
146                 // default load address to memory block base address
147
loadAddress = ((IMemoryBlockExtension)descriptor.getMemoryBlock()).getBigBaseAddress();
148                 descriptor.setLoadAddress(loadAddress);
149             }
150             
151             // if address is still out of range, throw an exception
152
if (loadAddress.compareTo(mbStart) < 0 || loadAddress.compareTo(mbEnd) > 0)
153             {
154                 throw new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.TableRenderingContentProvider_0 + loadAddress.toString(16), null));
155             }
156             
157             int addressableUnitsPerLine = rendering.getAddressableUnitPerLine();
158             BigInteger JavaDoc bufferStart = loadAddress.subtract(BigInteger.valueOf(descriptor.getPreBuffer()*addressableUnitsPerLine));
159             BigInteger JavaDoc bufferEnd = loadAddress.add(BigInteger.valueOf(descriptor.getPostBuffer()*addressableUnitsPerLine));
160             bufferEnd = bufferEnd.add(BigInteger.valueOf(descriptor.getNumLines()*addressableUnitsPerLine));
161             
162             // TODO: should rely on input to tell us what to load
163
// instead of having the content adapter override the setting
164
if (descriptor.isDynamicLoad())
165             {
166                 if (bufferStart.compareTo(mbStart) < 0)
167                     bufferStart = mbStart;
168                 
169                 if (bufferEnd.compareTo(mbEnd) > 0)
170                 {
171                     bufferEnd = mbEnd;
172                     
173                     int numLines = bufferEnd.subtract(bufferStart).divide(BigInteger.valueOf(addressableUnitsPerLine)).intValue();
174                     if (numLines < descriptor.getNumLines())
175                     {
176                         // re-calculate buffer start since we may not have enough lines to popoulate the view
177
bufferStart = bufferEnd.subtract(BigInteger.valueOf(descriptor.getNumLines()*addressableUnitsPerLine));
178                         bufferStart = bufferStart.subtract(BigInteger.valueOf(descriptor.getPreBuffer()*addressableUnitsPerLine));
179                     }
180                 }
181                 
182                 // buffer end must be greater than buffer start
183
if (bufferEnd.compareTo(bufferStart) <= 0)
184                     throw new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.TableRenderingContentProvider_1, null));
185                 
186                 int numLines = bufferEnd.subtract(bufferStart).divide(BigInteger.valueOf(addressableUnitsPerLine)).intValue()+1;
187                 // get stoarage to fit the memory view tab size
188
return getMemoryToFitTable(bufferStart, numLines,context);
189             }
190             else
191             {
192                 if (bufferStart.compareTo(mbStart) < 0)
193                     bufferStart = mbStart;
194                 
195                 if (bufferEnd.compareTo(mbEnd) > 0)
196                 {
197                     bufferStart = mbEnd.subtract(BigInteger.valueOf((descriptor.getNumLines()-1)*addressableUnitsPerLine));
198                 }
199                 
200                 // buffer end must be greater than buffer start
201
if (bufferEnd.compareTo(bufferStart) <= 0)
202                     throw new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.TableRenderingContentProvider_2, null));
203                 
204                 int numLines = descriptor.getNumLines();
205                 // get stoarage to fit the memory view tab size
206
return getMemoryToFitTable(bufferStart, numLines, context);
207             }
208         }
209         return EMPTY;
210     }
211     
212     /**
213      * Get memory to fit table
214      * @param startingAddress
215      * @param numberOfLines
216      * @param updateDelta
217      * @throws DebugException
218      */

219     public Object JavaDoc[] getMemoryToFitTable(BigInteger JavaDoc startAddress, long numberOfLines, MemoryViewPresentationContext context) throws DebugException
220     {
221         AbstractAsyncTableRendering tableRendering = getTableRendering(context);
222         if (tableRendering == null)
223         {
224             DebugException e = new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.MemoryViewContentProvider_Unable_to_retrieve_content, null));
225             throw e;
226         }
227         
228         TableRenderingContentDescriptor descriptor = (TableRenderingContentDescriptor)tableRendering.getAdapter(TableRenderingContentDescriptor.class);
229         if(descriptor == null)
230             return new Object JavaDoc[0];
231         
232         // do not ask for memory from memory block if the debug target
233
// is already terminated
234
IDebugTarget target = descriptor.getMemoryBlock().getDebugTarget();
235         
236         if (target.isDisconnected() || target.isTerminated())
237             return new Object JavaDoc[0];
238         
239         boolean error = false;
240         DebugException dbgEvt = null;
241         
242         String JavaDoc adjustedAddress = startAddress.toString(16);
243
244         // align to the closest boundary based on addressable size per line
245
if (descriptor.isAlignAddressToBoundary() && descriptor.getMemoryBlock() instanceof IMemoryBlockExtension)
246         {
247             startAddress = MemoryViewUtil.alignToBoundary(startAddress, tableRendering.getAddressableUnitPerLine());
248         }
249
250         IMemoryBlockExtension extMemoryBlock = null;
251         MemoryByte[] memoryBuffer = null;
252         
253         long reqNumBytes = 0;
254         try
255         {
256             
257             if (descriptor.getMemoryBlock() instanceof IMemoryBlockExtension)
258             {
259                 reqNumBytes = tableRendering.getBytesPerLine() * numberOfLines;
260                 // get memory from memory block
261
extMemoryBlock = (IMemoryBlockExtension) descriptor.getMemoryBlock();
262                 
263                 long reqNumberOfUnits = tableRendering.getAddressableUnitPerLine() * numberOfLines;
264                         
265                 memoryBuffer = extMemoryBlock.getBytesFromAddress(startAddress, reqNumberOfUnits);
266         
267                 if(memoryBuffer == null)
268                 {
269                     DebugException e = new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.MemoryViewContentProvider_Unable_to_retrieve_content, null));
270                     throw e;
271                 }
272             }
273             else
274             {
275                 // get memory from memory block
276
byte[] memory = descriptor.getMemoryBlock().getBytes();
277                 
278                 if (memory == null)
279                 {
280                     DebugException e = new DebugException(DebugUIPlugin.newErrorStatus(DebugUIMessages.MemoryViewContentProvider_Unable_to_retrieve_content, null));
281                     throw e;
282                 }
283                 
284                 int prefillNumBytes = 0;
285                 
286                 // number of bytes need to prefill
287
if (!startAddress.toString(16).endsWith("0")) //$NON-NLS-1$
288
{
289                     adjustedAddress = startAddress.toString(16).substring(0, adjustedAddress.length() - 1);
290                     adjustedAddress += "0"; //$NON-NLS-1$
291
BigInteger JavaDoc adjustedStart = new BigInteger JavaDoc(adjustedAddress, 16);
292                     prefillNumBytes = startAddress.subtract(adjustedStart).intValue();
293                     startAddress = adjustedStart;
294                 }
295                 reqNumBytes = descriptor.getMemoryBlock().getLength() + prefillNumBytes;
296                 
297                 // figure out number of dummy bytes to append
298
while (reqNumBytes % tableRendering.getBytesPerLine() != 0)
299                 {
300                     reqNumBytes ++;
301                 }
302                 
303                 numberOfLines = reqNumBytes / tableRendering.getBytesPerLine();
304                 
305                 // create memory byte for IMemoryBlock
306
memoryBuffer = new MemoryByte[(int)reqNumBytes];
307                 
308                 // prefill buffer to ensure double-word alignment
309
for (int i=0; i<prefillNumBytes; i++)
310                 {
311                     MemoryByte tmp = new MemoryByte();
312                     tmp.setValue((byte)0);
313                     tmp.setWritable(false);
314                     tmp.setReadable(false);
315                     tmp.setEndianessKnown(false);
316                     memoryBuffer[i] = tmp;
317                 }
318                 
319                 // fill buffer with memory returned by debug adapter
320
int j = prefillNumBytes; // counter for memoryBuffer
321
for (int i=0; i<memory.length; i++)
322                 {
323                     MemoryByte tmp = new MemoryByte();
324                     tmp.setValue(memory[i]);
325                     tmp.setReadable(true);
326                     tmp.setWritable(true);
327                     tmp.setEndianessKnown(false);
328                     memoryBuffer[j] = tmp;
329                     j++;
330                 }
331                 
332                 // append to buffer to fill up the entire line
333
for (int i=j; i<memoryBuffer.length; i++)
334                 {
335                     MemoryByte tmp = new MemoryByte();
336                     tmp.setValue((byte)0);
337                     tmp.setWritable(false);
338                     tmp.setReadable(false);
339                     tmp.setEndianessKnown(false);
340                     memoryBuffer[i] = tmp;
341                 }
342             }
343         }
344         catch (DebugException e)
345         {
346             memoryBuffer = makeDummyContent(numberOfLines, tableRendering.getBytesPerLine());
347             
348             // finish creating the content provider before throwing an event
349
error = true;
350             dbgEvt = e;
351         }
352         catch (Throwable JavaDoc e)
353         {
354             // catch all errors from this process just to be safe
355
memoryBuffer = makeDummyContent(numberOfLines, tableRendering.getBytesPerLine());
356             
357             // finish creating the content provider before throwing an event
358
error = true;
359             dbgEvt = new DebugException(DebugUIPlugin.newErrorStatus(e.getMessage(), e));
360         }
361         
362         // if debug adapter did not return enough memory, create dummy memory
363
if (memoryBuffer.length < reqNumBytes)
364         {
365             ArrayList JavaDoc newBuffer = new ArrayList JavaDoc();
366             
367             for (int i=0; i<memoryBuffer.length; i++)
368             {
369                 newBuffer.add(memoryBuffer[i]);
370             }
371             
372             for (int i=memoryBuffer.length; i<reqNumBytes; i++)
373             {
374                 MemoryByte mb = new MemoryByte();
375                 mb.setReadable(false);
376                 mb.setWritable(false);
377                 mb.setEndianessKnown(false);
378                 newBuffer.add(mb);
379             }
380             
381             memoryBuffer = (MemoryByte[])newBuffer.toArray(new MemoryByte[newBuffer.size()]);
382             
383         }
384
385         boolean manageDelta = true;
386         
387         // If change information is not managed by the memory block
388
// The view tab will manage it and calculate delta information
389
// for its content cache.
390
if (descriptor.getMemoryBlock() instanceof IMemoryBlockExtension)
391         {
392             manageDelta = !((IMemoryBlockExtension)descriptor.getMemoryBlock()).supportsChangeManagement();
393         }
394             
395         if (error){
396             throw dbgEvt;
397         }
398         
399         // put memory information into MemoryViewLine
400
return organizeLines(numberOfLines, memoryBuffer, startAddress, manageDelta, context);
401         
402
403     }
404
405     private Object JavaDoc[] organizeLines(long numberOfLines, MemoryByte[] memoryBuffer, BigInteger JavaDoc address, boolean manageDelta, MemoryViewPresentationContext context)
406     {
407         Vector JavaDoc lineCache = new Vector JavaDoc();
408         IMemoryRendering rendering = context.getRendering();
409         if (!(rendering instanceof AbstractAsyncTableRendering))
410             return lineCache.toArray();
411         
412         AbstractAsyncTableRendering tableRendering = (AbstractAsyncTableRendering)rendering;
413         int addressableUnit = tableRendering.getBytesPerLine()/tableRendering.getAddressableSize();
414         
415         for (int i = 0; i < numberOfLines; i++)
416         {
417             int bytesPerLine = tableRendering.getBytesPerLine();
418             MemoryByte[] memory = new MemoryByte[bytesPerLine];
419             
420             // counter for memory, starts from 0 to number of bytes per line
421
int k = 0;
422             // j is the counter for memArray, memory returned by debug adapter
423
for (int j = i * bytesPerLine;
424                 j < i * bytesPerLine + bytesPerLine;
425                 j++)
426             {
427                 
428                 byte changeFlag = memoryBuffer[j].getFlags();
429                 if (manageDelta)
430                 {
431                     // turn off both change and known bits to make sure that
432
// the change bits returned by debug adapters do not take
433
// any effect
434

435                     changeFlag |= MemoryByte.HISTORY_KNOWN;
436                     changeFlag ^= MemoryByte.HISTORY_KNOWN;
437                     
438                     changeFlag |= MemoryByte.CHANGED;
439                     changeFlag ^= MemoryByte.CHANGED;
440                 }
441                 
442                 MemoryByte newByteObj = new MemoryByte(memoryBuffer[j].getValue(), changeFlag);
443                 memory[k] = newByteObj;
444                 k++;
445             }
446             
447             MemorySegment newLine = new MemorySegment(address, memory, addressableUnit);
448             lineCache.add(newLine);
449             address = address.add(BigInteger.valueOf(addressableUnit));
450         }
451         return lineCache.toArray();
452     }
453     
454     /**
455      * @param numberOfLines
456      * @return an array of dummy MemoryByte
457      */

458     private MemoryByte[] makeDummyContent(long numberOfLines, int bytesPerLine) {
459         MemoryByte[] memoryBuffer;
460         // make up dummy memory, needed for recovery in case the debug adapter
461
// is capable of retrieving memory again
462

463         int numBytes = (int)(bytesPerLine * numberOfLines);
464         memoryBuffer = new MemoryByte[numBytes];
465         
466         for (int i=0; i<memoryBuffer.length; i++){
467             memoryBuffer[i] = new MemoryByte();
468             memoryBuffer[i].setValue((byte)0);
469             memoryBuffer[i].setWritable(false);
470             memoryBuffer[i].setReadable(false);
471             memoryBuffer[i].setEndianessKnown(false);
472         }
473         return memoryBuffer;
474     }
475     
476     protected AbstractAsyncTableRendering getTableRendering(MemoryViewPresentationContext context)
477     {
478         IMemoryRendering memRendering = context.getRendering();
479         if (memRendering != null && memRendering instanceof AbstractAsyncTableRendering)
480         {
481             return (AbstractAsyncTableRendering)memRendering;
482         }
483         return null;
484     }
485 }
486
Popular Tags