/* * 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; } }