/*
* Copyright (c) 2010-2012 Research In Motion Limited. All rights reserved.
*
* This program and the accompanying materials are made available
* under the terms of the Eclipse Public License, Version 1.0,
* which accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*
*/
package net.rim.ejde.internal.sourcelookup;
import java.io.File;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.debug.core.DebugException;
import org.eclipse.jdt.debug.core.IJavaReferenceType;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.IJavaType;
import org.eclipse.jdt.debug.core.IJavaValue;
import org.eclipse.jdt.launching.sourcelookup.containers.JavaSourceLookupParticipant;
import com.sun.jdi.VMDisconnectedException;
public class RIMSourceLookupParticipant extends JavaSourceLookupParticipant {
/**
*
* Returns the source name associated with the given object, or <code>null</code> if none.
*
* @param object
* an object with an <code>IJavaStackFrame</code> adapter, an IJavaValue or an IJavaType
* @return the source name associated with the given object, or <code>null</code> if none
* @exception CoreException
* if unable to retrieve the source name
* @see org.eclipse.jdt.internal.debug.core.JavaDebugUtils#getSourceName(Object)
*/
public String getSourceName( Object object ) throws CoreException {
if( object instanceof String ) {
// assume it's a file name
return (String) object;
}
IJavaStackFrame frame = null;
if( object instanceof IAdaptable ) {
frame = (IJavaStackFrame) ( (IAdaptable) object ).getAdapter( IJavaStackFrame.class );
}
String typeName = null;
try {
if( frame != null ) {
if( frame.isObsolete() ) {
return null;
}
String sourceName = frame.getSourcePath();
// TODO: this may break fix to bug 21518
if( sourceName == null ) {
// no debug attributes, guess at source name
typeName = frame.getDeclaringTypeName();
} else {
return sourceName;
}
} else {
if( object instanceof IJavaValue ) {
// look at its type
object = ( (IJavaValue) object ).getJavaType();
}
if( object instanceof IJavaReferenceType ) {
IJavaReferenceType refType = (IJavaReferenceType) object;
String[] sourcePaths = refType.getSourcePaths( null );
if( sourcePaths != null && sourcePaths.length > 0 ) {
return sourcePaths[ 0 ];
}
}
if( object instanceof IJavaType ) {
typeName = ( (IJavaType) object ).getName();
}
}
} catch( DebugException e ) {
int code = e.getStatus().getCode();
if( code == IJavaThread.ERR_THREAD_NOT_SUSPENDED || code == IJavaStackFrame.ERR_INVALID_STACK_FRAME
|| e.getStatus().getException() instanceof VMDisconnectedException ) {
return null;
}
throw e;
}
if( typeName != null ) {
return generateSourceName( typeName );
}
return null;
}
/**
*
* Generates and returns a source file path based on a qualified type name. For example, when <code>java.lang.String</code> is
* provided, the returned source name is <code>java/lang/String.java</code>.
*
* @param qualifiedTypeName
* fully qualified type name that may contain inner types denoted with <code>$</code> character
* @return a source file path corresponding to the type name
* @see org.eclipse.jdt.internal.debug.core.JavaDebugUtils#generateSourceName(String)
*/
public static String generateSourceName( String qualifiedTypeName ) {
int index = qualifiedTypeName.lastIndexOf( '.' );
if( index < 0 ) {
index = 0;
}
qualifiedTypeName = qualifiedTypeName.replace( '.', File.separatorChar );
index = qualifiedTypeName.indexOf( '$' );
if( index >= 0 ) {
qualifiedTypeName = qualifiedTypeName.substring( 0, index );
}
if( qualifiedTypeName.length() == 0 ) {
// likely a proxy class (see bug 40815)
qualifiedTypeName = null;
} else {
qualifiedTypeName = qualifiedTypeName + ".java"; //$NON-NLS-1$
}
return qualifiedTypeName;
}
}