/*
* 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.builders;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.rim.ejde.internal.core.ContextManager;
import net.rim.ejde.internal.core.IRIMMarker;
import net.rim.ejde.internal.model.BasicBlackBerryProperties.AlternateEntryPoint;
import net.rim.ejde.internal.model.BlackBerryProject;
import net.rim.ejde.internal.model.BlackBerryProperties;
import net.rim.ejde.internal.util.Messages;
import net.rim.ejde.internal.util.NatureUtils;
import net.rim.ejde.internal.util.ResourceBuilderUtils;
import net.rim.ejde.internal.util.VMUtils;
import org.apache.log4j.Logger;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CategorizedProblem;
import org.eclipse.swt.widgets.Display;
/**
* The Class CompilerToProjectEditorManager is used to manage markers that can be generated both by the app descriptor and the
* compiler.
*/
public class CompilerToAppDescriptorManager {
/** The _lib main marker map. */
private static Map< IJavaProject, List< IMarker >> _managedMarkerMap;
/** The _managed problem map. */
private static Map< ICompilationUnit, List< CategorizedProblem >> _managedProblemMap;
/** The _problem to marker map. */
private static Map< CategorizedProblem, IMarker > _problemToMarkerMap;
/** The Constant _log. */
static final Logger _log = Logger.getLogger( CompilerToAppDescriptorManager.class );
/** The INSTANCE. */
private static CompilerToAppDescriptorManager INSTANCE;
/**
* Gets the single instance of LibMainMethodManager.
*
* @return single instance of LibMainMethodManager
*/
public static CompilerToAppDescriptorManager getInstance() {
if( INSTANCE == null ) {
INSTANCE = new CompilerToAppDescriptorManager();
}
return INSTANCE;
}
/**
* Instantiates a new compiler to project editor manager.
*/
private CompilerToAppDescriptorManager() {
super();
_managedMarkerMap = new HashMap< IJavaProject, List< IMarker > >();
_managedProblemMap = new HashMap< ICompilationUnit, List< CategorizedProblem > >();
_problemToMarkerMap = new HashMap< CategorizedProblem, IMarker >();
}
/**
* Check for the error caused by having a libMain and not setting AutoStartup
*
* @param cu
* the cu
*
* @throws JavaModelException
* the java model exception
* @throws CoreException
* the core exception
*/
private void findLibMainInCU( ICompilationUnit cu ) throws JavaModelException, CoreException {
IType primaryType;
if( cu != null ) {
primaryType = cu.findPrimaryType();
if( primaryType == null ) {
if( ( cu.getAllTypes() != null ) && ( cu.getAllTypes().length > 0 ) ) {
primaryType = cu.getAllTypes()[ 0 ];
} else {
return;
}
}
final IMethod libMainMethod = primaryType.getMethod( "libMain", new String[] { "[QString;" } ); //$NON-NLS-1$ //$NON-NLS-2$
if( libMainMethod.exists() && ( libMainMethod.getExceptionTypes().length == 0 )
&& Flags.isStatic( libMainMethod.getFlags() ) && Flags.isPublic( libMainMethod.getFlags() ) ) {
final IJavaProject javaProject = cu.getJavaProject();
IProject project = javaProject.getProject();
if( NatureUtils.hasBBNature( project ) ) {
BlackBerryProperties properties = ContextManager.PLUGIN.getBBProperties( project.getName(), false );
if( properties._application.getType().equals( BlackBerryProject.LIBRARY )
&& !properties._application.isAutostartup().booleanValue() ) {
Display.getDefault().asyncExec( new Runnable() {
@Override
public void run() {
IMarker problem;
try {
problem = libMainMethod.getResource().createMarker( IRIMMarker.BLACKBERRY_PROBLEM );
int startPos = libMainMethod.getSourceRange().getOffset(), endPos = startPos
+ libMainMethod.getSourceRange().getLength() - 1;
problem.setAttributes(
new String[] { IMarker.MESSAGE, IMarker.CHAR_START, IMarker.CHAR_END,
IMarker.SEVERITY, IRIMMarker.ID },
new Object[] { Messages.CompilerToProjectEditorManager_libWarnMsg,
Integer.valueOf( startPos ), Integer.valueOf( endPos ),
Integer.valueOf( IMarker.SEVERITY_WARNING ),
Integer.valueOf( IRIMMarker.LIBMAIN_PROBLEM_ID ) } );
addManagedMarker( javaProject, problem );
} catch( CoreException e ) {
_log.error( "LibMainMethodManager.add: ", e );
}
}
} );
}
}
}
}
}
/**
* Checks for the error caused by having a compile time field usage and setting autoStartup
*
* @param cu
* the cu
* @param problem
* the problem
* @param hasCompileTimeValue
* the has compile time value
*/
private void findCompileTimeFieldUse( final ICompilationUnit cu, final CategorizedProblem problem, boolean hasCompileTimeValue ) {
final boolean hasMarker = _problemToMarkerMap.get( problem ) != null;
if( !hasMarker && ( !hasCompileTimeValue ) ) {
Display.getDefault().asyncExec( new Runnable() {
@Override
public void run() {
IMarker marker;
try {
String preferenceLabel = VMUtils.convertCodeSignErrorMsgToPreferenceLabel(problem.getMessage());
Integer key = VMUtils.convertPreferenceLabelToKey(preferenceLabel);
marker = cu.getResource().createMarker( IRIMMarker.CODE_SIGN_PROBLEM_MARKER );
marker.setAttributes(
new String[] { IMarker.MESSAGE, IMarker.CHAR_START, IMarker.CHAR_END, IMarker.SEVERITY,
IRIMMarker.KEY, IRIMMarker.ID, IMarker.LOCATION },
new Object[] { problem.getMessage(), Integer.valueOf( problem.getSourceStart() ),
Integer.valueOf( problem.getSourceEnd() ), Integer.valueOf( IMarker.SEVERITY_WARNING ),key,
Integer.valueOf(IRIMMarker.FIELD_USAGE_CODE_SIGN_PROBLEM_ID),"line " +problem.getSourceLineNumber() } );
addMarkerForProblem( problem, marker );
} catch( CoreException e ) {
_log.error( "LibMainMethodManager.add: ", e );
}
}
} );
}
}
/**
* Checks if a given resource's BB project is set to autostartup
*
* @param res
* the res
*
* @return true, if is autostartup
*/
static private boolean isAutostartup( IResource res ) {
boolean isAutoStartup = false;
IProject project = res.getProject();
if( ( project != null ) && project.exists() && NatureUtils.hasBBNature( project ) ) {
BlackBerryProperties properties = ContextManager.getDefault().getBBProperties( project.getName(), false );
isAutoStartup |= properties._application.isAutostartup().booleanValue();
for( AlternateEntryPoint entryPoint : properties.getAlternateEntryPoints() ) {
isAutoStartup |= entryPoint.isAutostartup().booleanValue();
}
}
return isAutoStartup;
}
/**
* Deletes managed markers for a given project
*
* @param javaProject
* the java project
*/
private void deleteMarkersForProject( IJavaProject javaProject ) {
List< IMarker > recordedProblems = _managedMarkerMap.get( javaProject );
_managedMarkerMap.put( javaProject, null );
if( recordedProblems != null ) {
for( final IMarker problem : recordedProblems ) {
Display.getDefault().asyncExec( new Runnable() {
@Override
public void run() {
try {
problem.delete();
} catch( CoreException e ) {
_log.error( "LibMainMethodManager.clean: ", e );
}
}
} );
}
}
}
/**
* Delete managed problems and their associated markers for a given project
*
* @param project
* the project
* @param preserveProblems
* whether or not to preserve the root problems
*
* @throws CoreException
* the core exception
*/
private void deleteProblemsForProject( IJavaProject project, boolean preserveProblems ) throws CoreException {
Set< ICompilationUnit > cus = _managedProblemMap.keySet();
for( ICompilationUnit cu : cus ) {
if( cu.getJavaProject().equals( project ) ) {
deleteProblemsForCU( cu, preserveProblems );
}
}
}
/**
* Deletes the managed markers associated with a CompilationUnit
*
* @param cu
* the cu
*
* @throws CoreException
* the core exception
*/
private void deleteMarkersForCU( ICompilationUnit cu ) throws CoreException {
IMarker[] markers = cu.getResource().findMarkers( IRIMMarker.BLACKBERRY_PROBLEM, true, IResource.DEPTH_ZERO );
for( final IMarker marker : markers ) {
Object id = marker.getAttribute( IRIMMarker.ID );
if( id != null && id.equals( Integer.valueOf( IRIMMarker.LIBMAIN_PROBLEM_ID ) ) ) {
Display.getDefault().asyncExec( new Runnable() {
@Override
public void run() {
try {
marker.delete();
} catch( CoreException e ) {
_log.error( "LibMainMethodManager.clean: ", e );
}
}
} );
}
}
}
/**
* Delete the managed problems and their associated markers for a given CompilationUnit
*
* @param cu
* the cu
* @param preserveProblems
* whether or not to preserve the root problems
*
* @throws CoreException
* the core exception
*/
private void deleteProblemsForCU( ICompilationUnit cu, boolean preserveProblems ) throws CoreException {
List< CategorizedProblem > problems = _managedProblemMap.get( cu );
// Delete Root problems for CU
if( !preserveProblems ) {
_managedProblemMap.put( cu, null );
}
// Delete markers associated with problems for CU
if( problems != null ) {
for( CategorizedProblem problem : problems ) {
final IMarker marker = _problemToMarkerMap.get( problem );
if( marker != null ) {
_problemToMarkerMap.put( problem, null );
Display.getDefault().asyncExec( new Runnable() {
@Override
public void run() {
try {
marker.delete();
} catch( CoreException e ) {
_log.error( "LibMainMethodManager.clean: ", e );
}
}
} );
}
}
}
}
/**
* Called when a Compilation unit is being re-compiled so all problems must be deleted.
*
* @param cu
* the cu
*
* @throws CoreException
* the core exception
*/
public void onCompilationUnitCompile( ICompilationUnit cu ) throws CoreException {
deleteMarkersForCU( cu );
deleteProblemsForCU( cu, false );
findLibMainInCU( cu );
// No need to check for *** because the compiler will
}
/**
* Called when a project has had a clean compilation. This means all problems must be deleted for this project.
*
* @param javaProject
* the java project
*
* @throws CoreException
* the core exception
*/
public void onProjectClean( IJavaProject javaProject ) throws CoreException {
deleteMarkersForProject( javaProject );
deleteProblemsForProject( javaProject, false );
}
/**
* On qualified name field usage.
*
* @param problem
* the problem
* @param cu
* the cu
* @param hasCompileTimeValue
* the has compile time value
*/
public void onQualifiedNameFieldUsage( final CategorizedProblem problem, final ICompilationUnit cu,
boolean hasCompileTimeValue ) {
addManagedProblem( cu, problem );
findCompileTimeFieldUse( cu, problem, hasCompileTimeValue );
}
/**
* Called whenever the project properties have changes
*
* @param javaProject
* the java project
*/
static public void onProjectPropertiesChange( IJavaProject javaProject ) {
IProject project = javaProject.getProject();
boolean isAutoStartup = isAutostartup( javaProject.getProject() );
try {
if( isAutoStartup ) {
IMarker[] marks = project.findMarkers( IRIMMarker.CODE_SIGN_PROBLEM_MARKER, false, IResource.DEPTH_ONE );
if( marks.length == 0 ) {
// create a new marker
ResourceBuilderUtils.createProblemMarker( project, IRIMMarker.CODE_SIGN_PROBLEM_MARKER,
"Run On Startup entry point requires signing with key: RIM Runtime API", 0, IMarker.SEVERITY_WARNING );
}
} else {
ResourceBuilderUtils.cleanProblemMarkers( project, new String[] { IRIMMarker.CODE_SIGN_PROBLEM_MARKER },
IResource.DEPTH_ONE );
}
} catch( CoreException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// if( ( javaProject != null ) && javaProject.exists() ) {
// try {
// //Clean all the markers, they will be re-created if necessary
// deleteMarkersForProject( javaProject );
// //DO NOT delete the root problems, they will not be re-created without a compiler call
// deleteProblemsForProject( javaProject, true );
//
// for( IPackageFragment pkgFragment : javaProject.getPackageFragments() ) {
// for( ICompilationUnit cu : pkgFragment.getCompilationUnits() ) {
// if( cu.exists() ) {
// findLibMainInCU( cu );
// findCompileTimeFieldUseInCU( cu );
// }
// }
// }
// } catch( JavaModelException e ) {
// _log.error( "LibMainMethodManager.add: ", e );
// } catch( CoreException e ) {
// _log.error( "LibMainMethodManager.add: ", e );
// }
// }
}
/**
* Put problem in map.
*
* @param javaProject
* the java project
* @param problem
* the problem
*/
void addManagedMarker( IJavaProject javaProject, IMarker problem ) {
List< IMarker > recordedProblems = _managedMarkerMap.get( javaProject );
if( recordedProblems == null ) {
recordedProblems = new ArrayList< IMarker >();
}
recordedProblems.add( problem );
_managedMarkerMap.put( javaProject, recordedProblems );
}
/**
* Adds the managed problem.
*
* @param cu
* the cu
* @param problem
* the problem
*/
void addManagedProblem( ICompilationUnit cu, CategorizedProblem problem ) {
List< CategorizedProblem > recordedProblems = _managedProblemMap.get( cu );
if( recordedProblems == null ) {
recordedProblems = new ArrayList< CategorizedProblem >();
}
recordedProblems.add( problem );
_managedProblemMap.put( cu, recordedProblems );
}
/**
* Adds the marker for problem.
*
* @param problem
* the problem
* @param marker
* the marker
*/
void addMarkerForProblem( CategorizedProblem problem, IMarker marker ) {
_problemToMarkerMap.put( problem, marker );
}
}