/*
* 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 java.util.ArrayList;
import java.util.List;
import net.rim.ejde.internal.core.ContextManager;
import net.rim.ejde.internal.model.BlackBerryProjectCoreNature;
import net.rim.ejde.internal.ui.launchers.LaunchUtils;
import net.rim.ide.RIA;
import org.apache.log4j.Logger;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.sourcelookup.ISourceContainer;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.launching.IRuntimeClasspathEntry;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.sourcelookup.containers.JavaProjectSourceContainer;
import org.eclipse.jdt.launching.sourcelookup.containers.JavaSourcePathComputer;
import org.eclipse.jdt.launching.sourcelookup.containers.PackageFragmentRootSourceContainer;
/**
* An instance of this class is used to compute the source paths.
*/
public class RIMSourcePathComputer extends JavaSourcePathComputer {
static private Logger _log = Logger.getLogger( RIMSourcePathComputer.class );
public ISourceContainer[] computeSourceContainers( ILaunchConfiguration configuration, IProgressMonitor monitor )
throws CoreException {
_log.trace( "Entering RIMSourcePathComputer.computerSourceContainers()." );
// call super's method
IRuntimeClasspathEntry[] entries = JavaRuntime.computeUnresolvedSourceLookupPath( configuration );
IRuntimeClasspathEntry[] resolved = JavaRuntime.resolveSourceLookupPath( entries, configuration );
List< IRuntimeClasspathEntry > jarEntriesWithSourceAttached = new ArrayList< IRuntimeClasspathEntry >();
List< IRuntimeClasspathEntry > jarEntriesWithoutSourceAttached = new ArrayList< IRuntimeClasspathEntry >();
List< IRuntimeClasspathEntry > otherEntries = new ArrayList< IRuntimeClasspathEntry >();
// split entries into three types: jar with source attached, jar without source attached, others
splitClasspathEntries( resolved, jarEntriesWithSourceAttached, jarEntriesWithoutSourceAttached, otherEntries );
ArrayList< ISourceContainer > sourceContainers = new ArrayList< ISourceContainer >();
// other entries are added at the beginning of the source lookup path, then jars with source attached,
// then RIM source paths, then jars without source attached and then rim_net_api.jar
setContainerToList(
JavaRuntime.getSourceContainers( otherEntries.toArray( new IRuntimeClasspathEntry[ otherEntries.size() ] ) ),
sourceContainers );
setContainerToList( JavaRuntime.getSourceContainers( jarEntriesWithSourceAttached
.toArray( new IRuntimeClasspathEntry[ jarEntriesWithSourceAttached.size() ] ) ), sourceContainers );
// add all RIM internal source folders to the source lookup path
boolean riaSourcesFound = false;
IVMInstall vm = LaunchUtils.getVMFromConfiguration( configuration );
RIA ria = ContextManager.PLUGIN.getRIA( vm.getInstallLocation().getAbsolutePath() );
if( ria != null && ria.getInRIMMode() ) {
File[] files = ria.getSourcePath();
for( int i = 0; i < files.length; i++ ) {
_log.trace( "Adding directory " + files[ i ].getName() + " to source lookup path" );
sourceContainers.add( new RIMDirSourceContainer( files[ i ], true ) );
riaSourcesFound = true;
}
}
// add jars without source attached
setContainerToList( JavaRuntime.getSourceContainers( jarEntriesWithoutSourceAttached
.toArray( new IRuntimeClasspathEntry[ jarEntriesWithoutSourceAttached.size() ] ) ), sourceContainers );
/*
* If an ISourceContainer in the sourceContainers list is a PackageFragmentRootSourceContainer, then it has source
* attached. If it is a ExternalSrchiveSourceContainer, then it does not. If RIA source files were found and a
* PackageFragmentRootSourceContainer is found in the list, and it is net_rim_api, then source is attached, so move it to
* the end of the list in order for debugging with mirrors to work
*/
for( ISourceContainer iSourceContainer : sourceContainers ) {
if( riaSourcesFound && iSourceContainer instanceof PackageFragmentRootSourceContainer ) {
if( "net_rim_api.jar".equals( iSourceContainer.getName() ) ) {
sourceContainers.remove( iSourceContainer );
sourceContainers.add( iSourceContainer );
break;
}
}
}
_log.trace( "There are " + sourceContainers.size() + " source containers." );
return sourceContainers.toArray( new ISourceContainer[ 0 ] );
}
private void splitClasspathEntries( IRuntimeClasspathEntry[] entries,
List< IRuntimeClasspathEntry > jarEntriesWithSourceAttached,
List< IRuntimeClasspathEntry > jarEntriesWithoutSourceAttached, List< IRuntimeClasspathEntry > otherEntries ) {
for( int i = 0; i < entries.length; i++ ) {
if( entries[ i ].getType() != IRuntimeClasspathEntry.ARCHIVE ) {
otherEntries.add( entries[ i ] );
continue;
}
if( entries[ i ].getSourceAttachmentLocation() == null )
jarEntriesWithoutSourceAttached.add( entries[ i ] );
else
jarEntriesWithSourceAttached.add( entries[ i ] );
}
}
private void setContainerToList( ISourceContainer[] containers, List< ISourceContainer > list ) {
// add the java project ones first
for( int i = 0; i < containers.length; i++ ) {
if( containers[ i ] instanceof JavaProjectSourceContainer )
list.add( 0, containers[ i ] );
else
list.add( containers[ i ] );
}
}
protected void addProjectSourcePaths( List< ISourceContainer > sourceContainers ) throws CoreException {
// Add all RIM projects to the source lookup path
for( IProject project : ResourcesPlugin.getWorkspace().getRoot().getProjects() ) {
if( project.hasNature( BlackBerryProjectCoreNature.NATURE_ID ) ) {
IJavaProject javaProject = JavaCore.create( project );
_log.trace( "Adding project " + project.getName() + " to source lookup path" );
sourceContainers.add( new JavaProjectSourceContainer( javaProject ) );
}
}
}
}