/*
* 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.util;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import net.rim.ejde.internal.core.ContextManager;
import net.rim.ejde.internal.core.IConstants;
import net.rim.ejde.internal.core.IRIMMarker;
import net.rim.ejde.internal.model.BlackBerryProject;
import net.rim.ejde.internal.model.BlackBerryProjectCoreNature;
import net.rim.ejde.internal.model.BlackBerryProperties;
import net.rim.ejde.internal.model.BlackBerryPropertiesFactory;
import net.rim.ejde.internal.ui.dialogs.PreprocessHookInstallDialog;
import net.rim.ide.OSUtils;
import net.rim.ide.core.Util;
import net.rim.sdk.resourceutil.ResourceCollection;
import net.rim.sdk.resourceutil.ResourceCollectionFactory;
import net.rim.sdk.resourceutil.ResourceConstants;
import net.rim.sdk.resourceutil.ResourceElement;
import net.rim.sdk.resourceutil.ResourceLocale;
import org.apache.log4j.Logger;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelMarker;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.launching.IVMInstall;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.browser.IWebBrowser;
import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
import org.eclipse.ui.ide.ResourceUtil;
import org.osgi.framework.Bundle;
/**
* Helper class for projects
*
* @author jkeshavarzi
*/
public class ProjectUtils {
private static final Logger logger = Logger.getLogger( ProjectUtils.class );
/**
* Finds the given project in the workspace.
*
* @param projectName
* Name of the project to find.
* @return The IProject if it was found, null otherwise.
*/
public static IProject getProject( String projectName ) {
IProject projects[] = ResourcesPlugin.getWorkspace().getRoot().getProjects();
for( IProject project : projects ) {
if( project.getName().equalsIgnoreCase( projectName ) ) {
return project;
}
}
return null;
}
/**
* Locates all the source folders represented by type IPackageFragmentRoot.K_SOURCE for the given project.
*
* @param project
* The IProject to search for source folders.
* @return An IPackageFragmentRoot array containing each K_SOURCE fragment found for the given project.
*/
public static IPackageFragmentRoot[] getProjectSourceFolders( IProject project ) {
IJavaProject iJavaProject = JavaCore.create( project );
ArrayList< IPackageFragmentRoot > sourceRoots = new ArrayList< IPackageFragmentRoot >();
if( iJavaProject.exists() && iJavaProject.isOpen() ) {
try {
IPackageFragmentRoot[] roots = iJavaProject.getAllPackageFragmentRoots();
for( IPackageFragmentRoot root : roots ) {
if( IPackageFragmentRoot.K_SOURCE == root.getKind() ) {
sourceRoots.add( root );
}
}
} catch( JavaModelException e ) {
logger.error( "findProjectSources: Could not retrieve project sources:", e ); //$NON-NLS-1$
return new IPackageFragmentRoot[ 0 ];
}
}
return sourceRoots.toArray( new IPackageFragmentRoot[ sourceRoots.size() ] );
}
/**
* Checks the given project for a file with the given name
*
* @param project
* - The IProject to search for the file
* @param name
* - The name of the file to search for
* @param isPrefix
* - Indicates whether the passed in file name should be treated as a prefix when searching
* @return The found IFile object, or null if nothing was found
*/
public static IFile getProjectIFile( IProject project, String name, Boolean isPrefix ) {
IFile file = null;
// source folders
IPackageFragmentRoot roots[] = getProjectSourceFolders( project );
for( IPackageFragmentRoot root : roots ) {
try {
IJavaElement elements[] = root.getChildren();
for( IJavaElement element : elements ) {
if( element.getElementType() == IJavaElement.PACKAGE_FRAGMENT ) {
IPackageFragment packageFragment = (IPackageFragment) element;
Object packageChildren[] = packageFragment.getNonJavaResources();
for( Object child : packageChildren ) {
if( child instanceof IFile ) {
IFile childFile = (IFile) child;
if( isPrefix.booleanValue() ) {
if( childFile.getName().startsWith( name ) ) {
return childFile;
}
} else {
if( childFile.getName().equals( name ) ) {
return childFile;
}
}
}
}
}
}
} catch( JavaModelException e ) {
logger.error( "getProjectIFile: error" );
}
}
return file;
}
/**
* Get all files found in project
*
* @param project
* - The IProject to retrieve files
* @return A IFile array containing all found files within the passed in project
*/
public static IFile[] getProjectFiles( IProject project ) {
ArrayList< IFile > files = new ArrayList< IFile >();
// source folders
IPackageFragmentRoot roots[] = getProjectSourceFolders( project );
for( IPackageFragmentRoot root : roots ) {
try {
IJavaElement sourceElements[] = root.getChildren();
for( IJavaElement sourceElement : sourceElements ) {
if( sourceElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT ) {
IPackageFragment packageFragment = (IPackageFragment) sourceElement;
IJavaElement packageElements[] = packageFragment.getChildren();
for( IJavaElement packageElement : packageElements ) {
if( packageElement instanceof IFile ) {
files.add( (IFile) packageElement );
}
}
}
}
} catch( JavaModelException e ) {
logger.error( "getProjectFiles: error" );
}
}
return files.toArray( new IFile[ files.size() ] );
}
/**
* Returns the set of all referenced IProjects for a given IProject
*
* @param project
* the given IProject
* @return the array of referenced IProjects, calculated recursively
* @throws CoreException
* if an error occurs while computing referenced projects
*/
public static Set< IProject > getAllReferencedProjects( IProject project ) throws CoreException {
Set< IProject > referencedProjects = new HashSet< IProject >();
addReferencedProjects( project, referencedProjects );
return referencedProjects;
}
private static void addReferencedProjects( IProject project, Set< IProject > references ) throws CoreException {
if( project.isOpen() ) {
IJavaProject javaProject = JavaCore.create( project );
String[] requiredProjectNames = javaProject.getRequiredProjectNames();
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
IProject requiredProject = null;
for( String projectName : requiredProjectNames ) {
requiredProject = workspaceRoot.getProject( projectName );
if( requiredProject.exists() && requiredProject.isOpen() && !references.contains( requiredProject ) ) {
references.add( requiredProject );
addReferencedProjects( requiredProject, references );
}
}
}
}
/**
* Returns the array of all referenced IJavaProjects for a given IJavaProject
*
* @param project
* the given IJavaProject
* @return the array of referenced IJavaProjects, calculated recursively
* @throws CoreException
* if an error occurs while computing referenced projects
*/
public static List< IJavaProject > getAllReferencedJavaProjects( IJavaProject project ) throws CoreException {
Set< IProject > referencedProjects = new HashSet< IProject >();
List< IJavaProject > refJavaProjects = new ArrayList< IJavaProject >();
addReferencedProjects( project.getProject(), referencedProjects );
for( IProject proj : referencedProjects ) {
refJavaProjects.add( JavaCore.create( proj ) );
}
return refJavaProjects;
}
/**
* Returns the array of all referenced projects for a given <code>bbProject</code>.
* <p>
* <b>If the <code>bbProject</code> depends on some java projects, we created BB projects on-the-fly for those java
* projects.</b>
*
* @param bbProject
* the given BlackBerryProject
* @return the array of referenced BlackBerryProjects, calculated recursively
* @throws CoreException
* if an error occurs while computing referenced projects
*/
public static List< BlackBerryProject > getAllReferencedProjects( BlackBerryProject bbProject ) throws CoreException {
Set< IProject > referencedProjects = new HashSet< IProject >();
List< BlackBerryProject > refJavaProjects = new ArrayList< BlackBerryProject >();
addReferencedProjects( bbProject.getProject(), referencedProjects );
for( IProject proj : referencedProjects ) {
BlackBerryProperties properties = null;
final IJavaProject javaProject = JavaCore.create( proj );
if( proj.hasNature( BlackBerryProjectCoreNature.NATURE_ID ) ) {
properties = ContextManager.PLUGIN.getBBProperties( proj.getName(), false );
if( properties == null ) {
continue;
}
} else {
// create a BB properties for a java project on-the-fly
properties = BlackBerryPropertiesFactory.createBlackBerryProperties( javaProject );
;
}
refJavaProjects.add( new BlackBerryProject( javaProject, properties ) );
}
return refJavaProjects;
}
/**
* Determines whether a given IJavaProject represents a parent our of a list of selected projects
*
* @param project
* the given IJavaProject
* @param selectedProjects
* the selection of IJavaProjects
* @return
*/
public static boolean isParentProject( IJavaProject project, List< IJavaProject > selectedProjects ) {
IProject eclipseProj = project.getProject();
IProject[] projects = eclipseProj.getReferencingProjects();
for( IProject refProject : projects ) {
if( selectedProjects.contains( JavaCore.create( refProject ) ) ) {
return false;
}
}
return true;
}
/**
* Returns the set of all referenced IJavaProjects for a list of objects supposed to be IJavaProject
*
* @param javaProjects
* the list of objects supposed to be of type IJavaProject
* @return the set of referenced IJavaProjects, included the IJavaProjects themselves, calculated recursively
* @throws CoreException
* if an error occurs while computing referenced projects
*/
public static Set< IJavaProject > getAllJavaProjects( List< Object > javaProjects ) throws CoreException {
Set< IJavaProject > allJavaProjects = new HashSet< IJavaProject >();
Set< IProject > allProjects = new HashSet< IProject >();
for( Object obj : javaProjects ) {
if( obj instanceof IJavaProject ) {
IProject currentProject = ( (IJavaProject) obj ).getProject();
allProjects.add( currentProject );
addReferencedProjects( currentProject, allProjects );
for( IProject p : allProjects ) {
allJavaProjects.add( JavaCore.create( p ) );
}
}
}
return allJavaProjects;
}
/**
* Gets a file that exists in an Eclipse project.
* <p>
* TODO: Someone can probably optimize this method better. Like using some of the IWorkspaceRoot.find*() methods...
*
* @param project
* the Eclipse project the file belongs to
* @param file
* the File which is in the Eclipse project
* @return the Eclipse resource file associated with the file
*/
public static IResource getResource( IProject project, File file ) {
IJavaProject javaProject = JavaCore.create( project );
IPath filePath = new Path( file.getAbsolutePath() );
try {
IClasspathEntry[] classpathEntries = javaProject.getResolvedClasspath( true );
IFile input = null;
// Look for a source folder
for( IClasspathEntry classpathEntry : classpathEntries ) {
if( classpathEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE ) {
// Try to resolve the source container
IWorkspaceRoot workspaceRoot = project.getWorkspace().getRoot();
IResource resource = workspaceRoot.findMember( classpathEntry.getPath() );
if( resource instanceof IContainer ) {
IContainer sourceContainer = (IContainer) resource;
File sourceContainerFile = resource.getLocation().toFile();
IPath sourceFolderPath = new Path( sourceContainerFile.getAbsolutePath() );
// See if the file path is within this source folder
// path
if( sourceFolderPath.isPrefixOf( filePath ) ) {
int segmentCount = sourceFolderPath.segmentCount();
IPath relativePath = filePath.removeFirstSegments( segmentCount );
input = sourceContainer.getFile( relativePath );
break;
}
}
}
}
return input;
} catch( JavaModelException e ) {
e.printStackTrace();
return null;
}
}
/**
* Gets selected IJavaProjects from the selection.
*
* @param selection
* The <code>StructuredSelection</code>
* @return <code>IJavaProject</code>
*/
public static IJavaProject[] getSelectProjects( StructuredSelection selection ) {
StructuredSelection ss = selection;
List< IJavaProject > projects = new ArrayList< IJavaProject >();
Object p = null;
Iterator< Object > i = ss.iterator();
while( i.hasNext() ) {
p = i.next();
if( p instanceof IJavaProject ) {
try {
// we only package BB projects
if( ( (IJavaProject) p ).getProject().hasNature( BlackBerryProjectCoreNature.NATURE_ID ) ) {
projects.add( (IJavaProject) p );
}
} catch( CoreException e ) {
logger.error( e.getMessage() );
}
} else if( p instanceof IProject ) {
try {
// we only package BB projects
if( ( (IProject) p ).hasNature( BlackBerryProjectCoreNature.NATURE_ID ) ) {
projects.add( JavaCore.create( (IProject) p ) );
}
} catch( CoreException e ) {
logger.error( e.getMessage() );
}
}
}
return projects.toArray( new IJavaProject[ projects.size() ] );
}
/**
* Gets the IPath of the .project file of the given <code>project</code>.
*
* @param project
* @return
*/
public static IPath getProjectDescriptionFilePath( IProject project ) {
IFile iFile = project.getFile( ".project" );
return iFile.getLocation();
}
public static LinkedHashSet< BlackBerryProject > getProjectsByBuildOrder( Set< BlackBerryProject > selectedProjects )
throws CoreException {
Set< BlackBerryProject > allProjects = new HashSet< BlackBerryProject >();
for( BlackBerryProject project : selectedProjects ) {
if( project != null ) {
allProjects.addAll( ProjectUtils.getAllReferencedProjects( project ) );
allProjects.add( project );
}
}
LinkedHashSet< BlackBerryProject > sortedProjects = new LinkedHashSet< BlackBerryProject >( allProjects.size() );
Map< String, Boolean > visitHistory = new HashMap< String, Boolean >( allProjects.size() );
for( BlackBerryProject project : allProjects ) {
ProjectUtils.visitNode( project, visitHistory, sortedProjects );
}
return sortedProjects;
}
private static void visitNode( BlackBerryProject rootNode, Map< String, Boolean > visitHistory,
Set< BlackBerryProject > sortedProjects ) throws CoreException {
Boolean visited = visitHistory.get( rootNode.getElementName() );
if( visited == null ) {
visitHistory.put( rootNode.getElementName(), Boolean.TRUE );
for( BlackBerryProject childNode : ProjectUtils.getAllReferencedProjects( rootNode ) ) {
ProjectUtils.visitNode( childNode, visitHistory, sortedProjects );
}
sortedProjects.add( rootNode );
}
}
/**
* Gets non-BlackBerry projects in the given <code>javaProjects</code>.
*
* @param javaProjects
* @return
*/
public static List< IJavaProject > getNonBBJavaProjects( List< IJavaProject > javaProjects ) {
List< IJavaProject > nonBBProjects = new ArrayList< IJavaProject >();
for( IJavaProject javaProject : javaProjects ) {
try {
if( !javaProject.getProject().hasNature( BlackBerryProjectCoreNature.NATURE_ID ) ) {
nonBBProjects.add( javaProject );
}
} catch( CoreException e ) {
logger.error( e.getMessage() );
continue;
}
}
return nonBBProjects;
}
/**
* Gets non-BlackBerry java projects which have JDE compatibility problem in the given <code>javaProjects</code>.
*
* @param javaProjects
* non-BlackBerry java projects
* @return
*/
public static List< IJavaProject > getJavaProjectsContainJDKCompatibilityProblem( List< IJavaProject > javaProjects ) {
List< IJavaProject > projectWithProblem = new ArrayList< IJavaProject >();
for( IJavaProject javaProject : javaProjects ) {
if( hasJDKCompatibilityProblem( javaProject ) ) {
projectWithProblem.add( javaProject );
}
}
return projectWithProblem;
}
/**
* Checks if the given <code>javaProject</code> has compatibility problem.
*
* @param javaProject
* @return
*/
public static boolean hasJDKCompatibilityProblem( IJavaProject javaProject ) {
final Map map = javaProject.getOptions( true );
if( map.size() > 0 ) {
String value = (String) map.get( JavaCore.COMPILER_COMPLIANCE );
if( !value.equalsIgnoreCase( JavaCore.VERSION_1_4 ) ) {
return true;
}
value = (String) map.get( JavaCore.COMPILER_SOURCE );
if( !value.equalsIgnoreCase( JavaCore.VERSION_1_3 ) ) {
return true;
}
value = (String) map.get( JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM );
if( !value.equalsIgnoreCase( JavaCore.VERSION_1_2 ) ) {
return true;
}
}
return false;
}
/**
* Returns all BlackBerry project in workspace.
*
* @return All BlackBerry projects
* @throws CoreException
*/
public static Set< IProject > getAllBBProjectsAndDependencies() {
IProject[] allProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
List< IProject > bbProjects = new ArrayList< IProject >();
for( IProject project : allProjects ) {
if( NatureUtils.hasBBNature( project ) ) {
bbProjects.add( project );
}
}
Set< IProject > bbAndDependentProjects = new HashSet< IProject >();
bbAndDependentProjects.addAll( bbProjects );
try {
bbAndDependentProjects.addAll( ProjectUtils.getAllReferencedProjects( bbProjects ) );
} catch( CoreException e ) {
logger.error( "", e );
}
return bbAndDependentProjects;
}
/**
* Checks if the given <code>project</code> is dependent by any checked project in the <code>checkedProjects</code> but is not
* in the <code>dependentProjects</code>.
*
* @param project
* @param checkedProjects
* @param dependentProjects
* @return Project the first project which depends on the given <code>project</code>.
*/
public static IProject isDependedByOthers( IProject project, List< IProject > checkedProjects,
Set< IProject > dependentProjects ) {
for( Object obj : checkedProjects ) {
IProject checkedProject = (IProject) obj;
if( !dependentProjects.contains( checkedProject ) ) {
Set< IProject > depProjects;
try {
depProjects = ProjectUtils.getAllReferencedProjects( checkedProject );
} catch( CoreException e ) {
logger.error( "", e );
return null;
}
for( IProject depProject : depProjects ) {
if( project.equals( depProject ) ) {
return checkedProject;
}
}
}
}
return null;
}
/**
* Returns the VM assigned to build the given project.
*
* @param project
* The <code>IJavaProject</code>
* @return <code>IVMInstall</code>
*/
public static IVMInstall getVMForProject( IJavaProject project ) {
IVMInstall vm = null;
try {
vm = JavaRuntime.getVMInstall( project );
} catch( CoreException e ) {
logger.debug( "", e );
}
return vm;
}
/**
* Returns list of BlackBerryProject for the given iprojects.
*
* @param iprojects
* @return List of <code>BlackBerryProject</code>
*/
public static Set< BlackBerryProject > getBlackBerryProjects( Set< IProject > iprojects ) {
Set< BlackBerryProject > bbProjects = new HashSet< BlackBerryProject >();
for( IProject iproject : iprojects ) {
BlackBerryProperties properties = null;
final IJavaProject javaProject = JavaCore.create( iproject );
if( NatureUtils.hasBBNature( iproject ) ) {
properties = ContextManager.PLUGIN.getBBProperties( iproject.getName(), false );
if( properties == null ) {
continue;
}
} else {
// create a BB properties for a java project on-the-fly
properties = BlackBerryPropertiesFactory.createBlackBerryProperties( javaProject );
;
}
bbProjects.add( new BlackBerryProject( javaProject, properties ) );
}
return bbProjects;
}
/**
* Checks if the given <code>project</code> is depended by any BlackBerry project.
*
* @param project
* @return
*/
public static boolean isDependedByBBProject( IProject project ) {
IProject[] referedProjects = project.getReferencingProjects();
for( IProject referedProject : referedProjects ) {
try {
if( referedProject.hasNature( BlackBerryProjectCoreNature.NATURE_ID ) ) {
return true;
}
if( isDependedByBBProject( referedProject ) ) {
return true;
}
} catch( CoreException e ) {
logger.error( e.getMessage() );
}
}
return false;
}
/**
* Returns the set of all referenced IProjects for the given projects.
*
* @param projects
* the given projects
* @return the set of referenced IProjects, calculated recursively
* @throws CoreException
* if an error occurs while computing referenced projects
*/
public static Set< IProject > getAllReferencedProjects( List< IProject > projects ) throws CoreException {
Set< IProject > referencedProjects = new HashSet< IProject >();
for( IProject project : projects ) {
referencedProjects.addAll( getAllReferencedProjects( project ) );
}
return referencedProjects;
}
/**
* Extracts the BB projects from the given <code>workingSets</code>.
*
* @param workingSets
* The selected workingsets.
* @return BB projects in the selected workingsets.
*/
public static HashSet< BlackBerryProject > extractBBProjects( IWorkingSet[] workingSets ) {
HashSet< BlackBerryProject > projects = new HashSet< BlackBerryProject >();
if( workingSets != null ) {
BlackBerryProject bbProject = null;
for( IWorkingSet workingSet : workingSets ) {
Object[] selection = workingSet.getElements();
for( Object element : selection ) {
IResource resource = ResourceUtil.getResource( element );
if( resource != null ) {
bbProject = createBBProject( resource.getProject() );
if( bbProject != null ) {
projects.add( bbProject );
}
} else {
ResourceMapping mapping = ResourceUtil.getResourceMapping( element );
if( mapping != null ) {
IProject[] theProjects = mapping.getProjects();
for( IProject theProject : theProjects ) {
bbProject = createBBProject( theProject );
if( bbProject != null ) {
projects.add( bbProject );
}
}
}
}
}
}
}
return projects;
}
/**
* Creates a BlackBerryProject instance for the given <code>iProject</code>.
*
* @param iProject
* @return The BlackBerryProject instance for the given <code>iProject</code> or <code>null</code> if the
* <code>iProject</code> does not have BB nature or any exception has occurred.
*/
static public BlackBerryProject createBBProject( IProject iProject ) {
try {
// we only package BB projects
if( !iProject.hasNature( BlackBerryProjectCoreNature.NATURE_ID ) ) {
return null;
}
} catch( CoreException e ) {
logger.error( e.getMessage() );
return null;
}
BlackBerryProperties properties = null;
properties = ContextManager.PLUGIN.getBBProperties( iProject.getProject().getName(), false );
if( properties == null ) {
return null;
}
return new BlackBerryProject( JavaCore.create( iProject ), properties );
}
static public List< String > getContents( File file ) {
List< String > contents = new ArrayList< String >();
BufferedReader input = null;
try {
input = new BufferedReader( new FileReader( file ) );
String line = null; // not declared within while loop
while( ( line = input.readLine() ) != null ) {
contents.add( line );
}
} catch( IOException e ) {
logger.error( e );
} finally {
if( input != null ) {
try {
input.close();
} catch( IOException e ) {
logger.error( e );
}
}
}
return contents;
}
static public void commitContents( File file, List< String > contents ) {
BufferedWriter output = null;
try {
output = new BufferedWriter( new FileWriter( file ) );
for( int i = 0; i < contents.size(); i++ ) {
output.write( contents.get( i ) );
output.newLine();
}
output.flush();
} catch( IOException e ) {
logger.error( e );
} finally {
if( output != null ) {
try {
output.close();
} catch( IOException e ) {
logger.error( e );
}
}
}
}
static private IStatus updateEclipseConfig() {
IPath configFilePath = new Path( Platform.getInstallLocation().getURL().getPath() );
if( OSUtils.isMac() ) {
configFilePath = configFilePath.append( File.separator + "Eclipse.app" + File.separator + "Contents" + File.separator
+ "MacOS" + File.separator );
}
configFilePath = configFilePath.append( "eclipse.ini" );
File configFile = configFilePath.toFile();
if( !configFile.exists() ) {
logger.error( NLS.bind( Messages.PreprocessHookEclipseIniNotFoundErr, configFile.getPath() ) );
return StatusFactory
.createErrorStatus( NLS.bind( Messages.PreprocessHookEclipseIniNotFoundErr, configFile.getPath() ) );
}
try {
List< String > contents = getContents( configFile );
String osgiConfigString = "-Dosgi.framework.extensions=";
String osgiString = IConstants.EMPTY_STRING;
int osgiConfigLineIndex = -1;
// "-Dosgi.framework.extensions=" is a JVM argument, we have to add it after "-vmargs" line
int vmargIndex = -1;
boolean bundleExisting = false;
String line;
for( int i = 0; i < contents.size(); i++ ) {
line = contents.get( i );
if( line.trim().equals( "-vmargs" ) ) {
vmargIndex = i;
} else if( line.trim().startsWith( osgiConfigString ) ) {
if( line.indexOf( IConstants.PREPROCESSING_HOOK_FRGMENT_ID ) > 0 ) {
bundleExisting = true;
}
osgiConfigLineIndex = i;
osgiString = line;
}
}
if( osgiConfigLineIndex < 0 ) {
// "-Dosgi.framework.extensions=" is not there
osgiString = osgiConfigString + IConstants.PREPROCESSING_HOOK_FRGMENT_ID;
contents.add( vmargIndex + 1, osgiString );
} else {
if( bundleExisting ) {
// "-Dosgi.framework.extensions=" is there, we should recomment users to re-install ejde
return StatusFactory.createErrorStatus( Messages.PreprocessHookCanNotBeConfiguredErr );
} else {
contents.set( osgiConfigLineIndex, osgiString + "," + IConstants.PREPROCESSING_HOOK_FRGMENT_ID );
}
}
commitContents( configFile, contents );
return Status.OK_STATUS;
} catch( Exception ex ) {
logger.error( ex.getMessage() );
return StatusFactory.createErrorStatus( ex.getMessage() );
}
}
/**
* Install the preprocess hook. We do not need to actually add anything to the configuration.ini. We just need to restart the
* eclipse.
*/
static public void setPreprocessorHook() {
if( PreprocessHookInstallDialog.isDialogOn() ) {
return;
}
PreprocessHookInstallDialog.setIsDialogOn( true );
// need to clean the workspace after restart
ContextManager.getDefault().getPreferenceStore().setValue( IConstants.NEED_CLEAN_WORKSPACE_KEY, true );
Display.getDefault().asyncExec( new Runnable() {
public void run() {
int result = PreprocessHookInstallDialog.openQuestion( Messages.PreprocessHookInstallDialogTitle,
Messages.PreprocessHookInstallDialog_Text );
if( result == IDialogConstants.OK_ID ) {
IStatus status = updateEclipseConfig();
if( status.isOK() ) {
PlatformUI.getWorkbench().restart();
} else {
MessageDialog.openError( ContextManager.getActiveWorkbenchShell(), Messages.ErrorHandler_DIALOG_TITLE,
status.getMessage() );
}
}
}
} );
}
/**
* Open the project startup page if it's not already opened
*
*/
public static void openStartupPage() {
Bundle bundle = Platform.getBundle( ContextManager.PLUGIN_ID); //IConstants.DOC_PLUGIN_ID );
IPath pagePath = new Path( IConstants.START_UP_PAGE );
IPath folderPath = new Path( IConstants.START_UP_FOLDER );
IPath htmlFolderPath = new Path( IConstants.HTML_PAGE_FOLDER ); // may be empty
URL pageUrl = FileLocator.find( bundle, pagePath, null );
URL folderUrl = FileLocator.find( bundle, folderPath, null );
URL htmlFolderUrl = FileLocator.find( bundle, htmlFolderPath, null );
IWorkbenchBrowserSupport support = PlatformUI.getWorkbench().getBrowserSupport();
try {
// extract necessary files from jar into a cache, otherwise the images will not be
// displayed proplerly
FileLocator.toFileURL( folderUrl );
// Since startup page links to html page, we need to extract html content as well
FileLocator.toFileURL( htmlFolderUrl );
pageUrl = FileLocator.toFileURL( pageUrl );
IWebBrowser browser = support.createBrowser( IWorkbenchBrowserSupport.AS_EDITOR
| IWorkbenchBrowserSupport.NAVIGATION_BAR | IWorkbenchBrowserSupport.LOCATION_BAR
| IWorkbenchBrowserSupport.STATUS, IConstants.BROWSER_ID, null, null );
browser.openURL( pageUrl );
} catch( PartInitException e ) {
logger.error( "Could not open the start up page in the editor part", e ); //$NON-NLS-1$
} catch( IOException e ) {
logger.error( "Unable to convert URL", e ); //$NON-NLS-1$
}
}
/**
* Checks if the active workspace contains any projects
*
* @return
*/
public static boolean containsProjects() {
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
return projects.length > 0;
}
/**
* Checks if all projects are closed in the active workspace
*
* @return
*/
public static boolean isAllBBProjectsClosed() {
List< IProject > projects = Arrays.asList( ResourcesPlugin.getWorkspace().getRoot().getProjects() );
if( !projects.isEmpty() ) {
for( IProject project : projects ) {
if( project.isOpen() && NatureUtils.hasBBNature( project ) ) {
return false;
}
}
}
return true;
}
/**
* Use a simple breadth-first algorithm to check if the given <code>folder</code> and its children folders have bee updated
* after the <code>lastModifiedTimeStamp</code>.
*
* @param folder
* @param lastModifiedTimeStamp
* @return
*/
public static boolean hasFolderBeenUpdated( File folder, long lastModifiedTimeStamp ) {
File[] folders;
SimpleQueue queue = new SimpleQueue();
queue.offer( folder );
File elementFolder;
while( ( elementFolder = (File) queue.poll() ) != null ) {
if( elementFolder.lastModified() > lastModifiedTimeStamp ) {
return true;
}
folders = elementFolder.listFiles( new FileFilterImpl() );
for( int i = 0; i < folders.length; i++ ) {
queue.offer( folders[ i ] );
}
}
return false;
}
static private class FileFilterImpl implements FileFilter {
@Override
public boolean accept( File pathname ) {
if( pathname.isDirectory() ) {
return true;
}
return false;
}
}
/**
* This is a simple implementation of Queue.
*
*
*/
static public class SimpleQueue {
Vector< Object > _vector;
public SimpleQueue() {
_vector = new Vector< Object >();
}
/**
* Gets the first element and remove it from the queue.
*
* @return
*/
public synchronized Object poll() {
if( _vector.isEmpty() ) {
return null;
}
return _vector.remove( 0 );
}
/**
* Gets the first element but not remove it from the queue.
*
* @return
*/
public synchronized Object peak() {
if( _vector.isEmpty() ) {
return null;
}
return _vector.get( 0 );
}
/**
* Adds an element to the bottom of the queue.
*
* @param obj
*/
public synchronized void offer( Object obj ) {
_vector.addElement( obj );
}
}
/**
* Check if the projects in the given <code>project</code> have any critical problems.
*
* @param project
* @return
*/
public static boolean hasCriticalProblems( IProject project ) {
if( project == null ) {
return false;
}
try {
IMarker[] markers = project.findMarkers( IMarker.PROBLEM, true, IResource.DEPTH_INFINITE );
if( markers.length > 0 ) {
for( IMarker marker : markers ) {
if( isCriticalProblem( marker ) ) {
return true;
}
}
}
return false;
} catch( CoreException e ) {
logger.error( e );
return true;
}
}
/**
* Check if the projects in the given <code>resource</code> have any error of the given <code>types</code>.
*
* @param resource
* @return
*/
public static boolean hasError( IResource resource, String[] types ) {
if( resource == null ) {
return false;
}
try {
IMarker[] markers = resource.findMarkers( IMarker.PROBLEM, true, IResource.DEPTH_INFINITE );
if( markers.length > 0 ) {
for( IMarker marker : markers ) {
Integer severity = (Integer) marker.getAttribute( IMarker.SEVERITY );
if( severity != null ) {
if( severity.intValue() >= IMarker.SEVERITY_ERROR && typeMatch( marker, types ) ) {
return true;
}
}
}
}
return false;
} catch( CoreException e ) {
logger.error( e );
return true;
}
}
public static boolean typeMatch( IMarker marker, String[] types ) {
for( int i = 0; i < types.length; i++ ) {
try {
if( marker.isSubtypeOf( types[ i ] ) ) {
return true;
}
} catch( CoreException e ) {
logger.error( e.getMessage() );
}
}
return false;
}
/**
* Check if the marker is a critical problem.
*
* @param marker
* @return
* @throws CoreException
*/
public static boolean isCriticalProblem( IMarker marker ) throws CoreException {
Integer severity = (Integer) marker.getAttribute( IMarker.SEVERITY );
if( severity != null ) {
// TODO need to improve this rule
return ( severity.intValue() >= IMarker.SEVERITY_ERROR )
&& ( marker.getType().equals( IJavaModelMarker.JAVA_MODEL_PROBLEM_MARKER ) || ( marker
.isSubtypeOf( IRIMMarker.BLACKBERRY_PROBLEM ) && !marker.getType().equals(
IRIMMarker.PACKAGING_PROBLEM ) ) );
}
return false;
}
/**
* Get the map of all found resource collections in the given project and the projects it depends on.
*/
static public Map< String, RRHFile > getProjectResources( BlackBerryProject bbProject ) {
logger.trace( "****** Get resource for " + bbProject.getProject().getName() );
Map< String, RRHFile > rrhFileMap = new HashMap< String, RRHFile >();
List< IJavaProject > projects = null;
try {
projects = getAllReferencedJavaProjects( bbProject );
projects.add( 0, bbProject.getJavaProject() );
for( IJavaProject javaProject : projects ) {
getResourceFilesRecursively( javaProject, rrhFileMap );
}
} catch( CoreException e ) {
logger.error( e );
}
return rrhFileMap;
}
static protected void getResourceFilesRecursively( IJavaProject javaProject, Map< String, RRHFile > rrhFileMap )
throws CoreException {
// search for rrh files in the project
FileVisitor visitor = new FileVisitor( IConstants.RRH_FILE_EXTENSION, false );
javaProject.getProject().accept( visitor );
List< IFile > rrhFiles = visitor.getFiles();
String fileNameWithPackage, fileName;
Hashtable< String, String > constantsTable;
for( IFile file : rrhFiles ) {
fileNameWithPackage = PackageUtils.getRRHPackageID( file.getLocation().toFile() );
fileName = file.getName();
fileNameWithPackage += "." + fileName.substring( 0, fileName.indexOf( ResourceConstants.RRH_SUFFIX ) );
if( rrhFileMap.get( fileNameWithPackage ) != null ) {
logger.debug( "Found duplicated rrh file: " + fileNameWithPackage );
} else {
constantsTable = getKeysFromRRHFile( file.getLocation().toOSString() );
if( constantsTable != null ) {
rrhFileMap.put( fileNameWithPackage, new RRHFile( fileNameWithPackage, file, constantsTable ) );
}
}
}
// search for rrh interfaces in the jar files imported by the project
InternalProjectUtils.getResourcesFromJars( javaProject, rrhFileMap );
}
/**
* Get key&value pairs from the rrh file </code>rrhFilePath</code>.
*
* @param rrhFilePath
* @return
* @throws CoreException
*/
public static Hashtable< String, String > getKeysFromRRHFile( String rrhFilePath ) throws CoreException {
if( rrhFilePath == null || !new File( rrhFilePath ).exists() ) {
return null;
}
Hashtable< String, String > headerKey2Id = new Hashtable< String, String >();
Util.parseRRHFile( rrhFilePath, headerKey2Id );
ResourceCollection rc = null;
try {
rc = ResourceCollectionFactory.newResourceCollection( rrhFilePath );
ResourceLocale rootLocale = rc.getLocale( "" ); //$NON-NLS-1$
if( rootLocale != null ) {
ResourceElement[] elements = rootLocale.getResourceElements();
for( ResourceElement element : elements ) {
// Only allow single value keys in the title and description fields
if( element.isMulti() ) {
headerKey2Id.remove( element.getKey() );
}
}
}
return headerKey2Id;
} catch( Exception e ) {
logger.error( e.getMessage() ); //$NON-NLS-1$
return new Hashtable< String, String >();
}
}
/**
* Obtain the allowed startup tiers as an int array.
*
* @return startup tiers as an int array.
*/
public static int[] getStartupTiers() {
return StartupTiers.getAllowedTiers();
}
/**
* Obtain the allowed startup tiers as a String array.
*
* @return startup tiers as a String array
*/
public static String[] getStartupTierStrings() {
int[] allowedTiers = StartupTiers.getAllowedTiers();
String[] tiers = new String[ allowedTiers.length ];
for( int i = 0; i < allowedTiers.length; i++ ) {
tiers[ i ] = String.valueOf( allowedTiers[ i ] );
}
return tiers;
}
public static List< IFile > getProtectedFiles( IProject project ) throws CoreException {
FileVisitor visitor = new FileVisitor( IConstants.JAVA_EXTENSION, false );
project.accept( visitor );
return visitor.getFiles();
}
public static List< IFile > getKeyFiles( IProject project ) throws CoreException {
KeyFileVisitor visitor = new KeyFileVisitor();
project.accept( visitor );
return visitor.getFiles();
}
protected static class FileVisitor implements IResourceVisitor {
IJavaProject _javaProject;
String _fileExtension;
boolean _shouldOnClassPath;
List< IFile > _files;
public FileVisitor( String fileExtension, boolean shouldOnClassPath ) {
_fileExtension = fileExtension;
_shouldOnClassPath = shouldOnClassPath;
_files = new ArrayList< IFile >();
}
public boolean visit( IResource resource ) throws CoreException {
if( !( resource instanceof IFile ) ) {
return shouldBeSourceRoot( resource );
}
String extension = resource.getFileExtension();
if( extension != null && extension.equalsIgnoreCase( _fileExtension ) ) {
if( _javaProject == null ) {
_javaProject = JavaCore.create( resource.getProject() );
}
if( _shouldOnClassPath ) {
if( _javaProject.isOnClasspath( resource ) ) {
_files.add( (IFile) resource );
}
} else {
_files.add( (IFile) resource );
}
}
return false;
}
private boolean shouldBeSourceRoot( IResource resource ) {
if( resource instanceof IProject ) {
return true;
}
if( PackageUtils.isUnderSrcFolder( resource ) ) {
return true;
}
return false;
}
public List< IFile > getFiles() {
return _files;
}
}
/**
* Gets all the projects in the current workspace which refer to the given <code>projects</code> including the
* <code>projects</code> themselves.
*
* @param projects
* @return
*/
public static Set< IProject > getAllReferencingProjects( IProject[] projects ) {
Set< IProject > allProjects = new HashSet< IProject >();
IProject[] referencedProjects;
for( IProject project : projects ) {
allProjects.add( project );
referencedProjects = project.getReferencingProjects();
for( int i = 0; i < referencedProjects.length; i++ ) {
allProjects.add( referencedProjects[ i ] );
}
}
return allProjects;
}
private static class KeyFileVisitor implements IResourceVisitor {
List< IFile > _files;
public KeyFileVisitor() {
_files = new ArrayList< IFile >();
}
public boolean visit( IResource resource ) throws CoreException {
if( !( resource instanceof IFile ) ) {
return shouldBeSourceRoot( resource );
}
String extension = resource.getFileExtension();
if( extension != null ) {
if( extension.equalsIgnoreCase( IConstants.KEY_FILE_EXTENSION ) ) {
_files.add( (IFile) resource );
}
}
return false;
}
private boolean shouldBeSourceRoot( IResource resource ) {
if( resource instanceof IProject ) {
return true;
}
if( PackageUtils.isUnderSrcFolder( resource ) ) {
return true;
}
return false;
}
public List< IFile > getFiles() {
return _files;
}
}
/**
* This class hold the key information for a rrh file.
*
*
*/
static public class RRHFile {
IFile _file;
String _resourceClassName;
Hashtable< String, String > _keyTable;
public RRHFile( String resourceClassName, IFile file, Hashtable< String, String > keyTable ) {
_resourceClassName = resourceClassName;
_file = file;
_keyTable = keyTable;
}
public IFile getFile() {
return _file;
}
public Hashtable< String, String > getKeyTalbe() {
if( _keyTable == null && _file != null ) {
try {
_keyTable = getKeysFromRRHFile( _file.getLocation().toOSString() );
} catch( CoreException e ) {
logger.error( e );
}
}
return _keyTable;
}
public String getResourceClassName() {
return _resourceClassName;
}
}
/**
* Returns the highest VM used by given projects.
*
* @param projects
* The collection of <code>BlackBerryProject</code>
* @return The <code>IVMInstall</code>
*/
public static IVMInstall getVMForProjects( Collection< BlackBerryProject > projects ) {
IVMInstall targetVM = null;
List< IVMInstall > availableVMs = VMUtils.getInstalledBBVMs();
for( BlackBerryProject project : projects ) {
IVMInstall vm = ProjectUtils.getVMForProject( project );
// The VM must be available
if( vm != null && availableVMs.contains( vm ) ) {
if( targetVM != null ) {
// use the highest version of VM
if( vm.getId().compareTo( targetVM.getId() ) > 0 ) {
targetVM = vm;
}
} else {
targetVM = vm;
}
}
}
if( targetVM == null ) {
targetVM = VMUtils.getDefaultBBVM();
}
return targetVM;
}
/**
* Returns the JVM version as conventional last token
*
* @param iproj
* @return -like "6.0.0"
*/
public static String getVMVersionForProject( IProject iproj ) {
String ver = "";
IVMInstall ivmi = ProjectUtils.getVMForProject( JavaCore.create( iproj ) );
if( ivmi != null ) {
ver = ivmi.getId().substring( ivmi.getId().lastIndexOf( ' ' ) + 1 );
}
return ver;
}
/**
* Create the given <code>file</code> if it does not exist. Also, this methods creates the parent folder if it does not exist.
*
* @param file
* @return A File instance if the file has been successfully created otherwise return <code>null</code>.
*/
public static File createFile( File file ) {
if( !file.exists() ) {
File parent = file.getParentFile();
if( !parent.exists() ) {
parent.mkdirs();
}
try {
file.createNewFile();
} catch( IOException e ) {
logger.error( e );
}
}
if( !file.exists() ) {
return null;
}
return file;
}
}