Java tutorial
/******************************************************************************* * Copyright (c) 2004, 2007 IBM Corporation and others. All rights reserved. This * program and the accompanying materials are made available under the terms of * the Eclipse Public License v1.0 which accompanies this distribution, and is * available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: Sian January - initial version * Matt Chapman - add source of advice markers ******************************************************************************/ package org.eclipse.ajdt.internal.ui.markers; import java.io.File; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.aspectj.asm.IProgramElement; import org.aspectj.asm.IRelationship; import org.aspectj.weaver.AdviceKind; import org.aspectj.weaver.model.AsmRelationshipProvider; import org.eclipse.ajdt.core.AJLog; import org.eclipse.ajdt.core.model.AJProjectModelFacade; import org.eclipse.ajdt.core.model.AJProjectModelFactory; import org.eclipse.ajdt.internal.ui.preferences.AspectJPreferences; import org.eclipse.ajdt.internal.ui.text.UIMessages; import org.eclipse.ajdt.ui.IAJModelMarker; 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.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; /** * Class responsible for advice and declaration markers. Updates the markers for * a given project when it is built. */ public class UpdateAJMarkers { private final AJProjectModelFacade model; private final IProject project; private final IFile[] sourceFiles; private int fileCount; private int markerCount; /** * To update markers for the entire project * * @param project the poject that needs updating */ public UpdateAJMarkers(IProject project) { this.model = AJProjectModelFactory.getInstance().getModelForProject(project); this.project = project; this.sourceFiles = null; this.fileCount = 0; this.markerCount = 0; } /** * to update markers for the given files only. * * @param project the poject that needs updating * * @param sourceFiles List of Strings of absolute paths of files that * need updating * * @deprecated Use {@link UpdateAJMarkers#UpdateAJMarkers(IProject, IFile[])} instead */ public UpdateAJMarkers(IProject project, File[] sourceFiles) { this.model = AJProjectModelFactory.getInstance().getModelForProject(project); this.project = project; this.sourceFiles = DeleteAndUpdateAJMarkersJob.javaFileToIFile(sourceFiles, project); } /** * to update markers for the given files only. * * @param project the poject that needs updating * * @param sourceFiles List of Strings of absolute paths of files that * need updating * */ public UpdateAJMarkers(IProject project, IFile[] sourceFiles) { this.model = AJProjectModelFactory.getInstance().getModelForProject(project); this.project = project; this.sourceFiles = sourceFiles; } protected IStatus run(IProgressMonitor monitor) { AJLog.logStart("Create markers: " + project.getName()); if (sourceFiles != null) { addMarkersForFiles(monitor); } else { addMarkersForProject(monitor); } AJLog.logEnd(AJLog.BUILDER, "Create markers: " + project.getName(), "Finished creating markers for " + project.getName()); AJLog.log(AJLog.BUILDER, "Created " + markerCount + " markers in " + fileCount + " files"); return Status.OK_STATUS; } /** * creates new markers for an entire project */ private void addMarkersForProject(IProgressMonitor monitor) { if (!model.hasModel()) { return; } try { IJavaProject jProject = JavaCore.create(project); IPackageFragmentRoot[] fragRoots = jProject.getPackageFragmentRoots(); SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, fragRoots.length); subMonitor.beginTask("Add markers for " + project.getName(), fragRoots.length); for (int i = 0; i < fragRoots.length; i++) { if (fragRoots[i].getKind() == IPackageFragmentRoot.K_SOURCE) { IJavaElement[] frags = fragRoots[i].getChildren(); for (int j = 0; j < frags.length; j++) { Set<String> completedCUNames = new HashSet<String>(frags.length, 1.0f); IJavaElement[] cus = ((IPackageFragment) frags[j]).getChildren(); for (int k = 0; k < cus.length; k++) { // ignore any class files in the source folder (Bug 258698) if (cus[k].getElementType() == IJavaElement.COMPILATION_UNIT) { // ignore duplicate compilation units IResource resource = cus[k].getResource(); if (!completedCUNames.contains(resource.getName())) { subMonitor.subTask("Add markers for " + cus[k].getElementName()); addMarkersForFile((ICompilationUnit) cus[k], ((ICompilationUnit) cus[k]).getResource()); completedCUNames.add(resource.getName()); fileCount++; } if (subMonitor.isCanceled()) { throw new OperationCanceledException(); } } } } subMonitor.worked(1); } } } catch (JavaModelException e) { } } private void addMarkersForFiles(IProgressMonitor monitor) { SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, sourceFiles.length); for (int i = 0; i < sourceFiles.length; i++) { IJavaElement unit = JavaCore.create(sourceFiles[i]); if (unit != null && unit.exists() && unit instanceof ICompilationUnit) { subMonitor.subTask("Add markers for " + unit.getElementName()); addMarkersForFile((ICompilationUnit) unit, sourceFiles[i]); fileCount++; } if (subMonitor.isCanceled()) { throw new OperationCanceledException(); } subMonitor.worked(1); } } private void addMarkersForFile(ICompilationUnit cu, IResource resource) { Map<Integer, List<IRelationship>> annotationMap = model.getRelationshipsForFile(cu); for (Entry<Integer, List<IRelationship>> entry : annotationMap.entrySet()) { createMarker(resource, entry.getKey().intValue(), entry.getValue()); markerCount++; } } private void createMarker(IResource resource, int lineNumber, List<IRelationship> relationships) { String markerType = null; boolean hasRuntime = false; for (IRelationship relationship : relationships) { hasRuntime |= relationship.hasRuntimeTest(); String customMarkerType = getCustomMarker(relationship); if (customMarkerType != null) { // Create a marker of the saved type or don't create one. // user has configured a custom marker createCustomMarker(resource, customMarkerType, lineNumber, relationship); } else { // must repeat for each target since // each target may be of a different type List<String> targets = relationship.getTargets(); for (String target : targets) { String markerTypeForRelationship = getMarkerTypeForRelationship(relationship, target); if (markerTypeForRelationship != null) { if (markerType == null) { markerType = markerTypeForRelationship; } else if (!markerType.equals(markerTypeForRelationship)) { markerType = getCombinedMarkerType(markerType, markerTypeForRelationship, hasRuntime); } } } } } // end for // Create the marker if (markerType != null) { try { IMarker marker = resource.createMarker(markerType); marker.setAttribute(IMarker.LINE_NUMBER, lineNumber); String label; int numTargets = getNumTargets(relationships); if (numTargets == 1) { label = getMarkerLabel(relationships); } else { label = getMultipleMarkersLabel(numTargets); } marker.setAttribute(IMarker.MESSAGE, label); marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH); } catch (CoreException e) { } } } private int getNumTargets(List<IRelationship> relationships) { int numTargets = 0; for (IRelationship rel : relationships) { for (String target : rel.getTargets()) { if (!rel.getName().equals(AsmRelationshipProvider.MATCHES_DECLARE)) { numTargets++; } } } return numTargets; } private void createCustomMarker(IResource resource, String customMarkerType, int lineNumber, IRelationship relationship) { if (!customMarkerType.equals(AJMarkersDialog.NO_MARKERS)) { try { IMarker marker = resource.createMarker(IAJModelMarker.CUSTOM_MARKER); marker.setAttribute(IMarker.LINE_NUMBER, lineNumber); String label; label = getMarkerLabel(relationship); marker.setAttribute(IMarker.MESSAGE, label); marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH); marker.setAttribute(CustomMarkerImageProvider.IMAGE_LOCATION_ATTRIBUTE, customMarkerType); } catch (CoreException e) { } } } /** * Get the marker type that should be used for the given relationship * * @param relationship * @param target * @return */ private String getMarkerTypeForRelationship(IRelationship relationship, String target) { String name = relationship.getName(); boolean runtimeTest = relationship.hasRuntimeTest(); String markerType; if (name.equals(AsmRelationshipProvider.ADVISED_BY)) { IProgramElement advice = model.getProgramElement(target); AdviceKind ak; if (advice.getExtraInfo() != null) { ak = AdviceKind.stringToKind(advice.getExtraInfo().getExtraAdviceInformation()); } else { ak = null; } if (runtimeTest) { if (ak == null) { markerType = IAJModelMarker.DYNAMIC_ADVICE_MARKER; } else if (ak == AdviceKind.Before) { markerType = IAJModelMarker.DYNAMIC_BEFORE_ADVICE_MARKER; } else if (ak == AdviceKind.After || ak == AdviceKind.AfterReturning || ak == AdviceKind.AfterThrowing) { markerType = IAJModelMarker.DYNAMIC_AFTER_ADVICE_MARKER; } else if (ak == AdviceKind.Around) { markerType = IAJModelMarker.DYNAMIC_AROUND_ADVICE_MARKER; } else { markerType = IAJModelMarker.DYNAMIC_ADVICE_MARKER; } } else { // no runtime test if (ak == null) { markerType = IAJModelMarker.ADVICE_MARKER; } else if (ak == AdviceKind.Before) { markerType = IAJModelMarker.BEFORE_ADVICE_MARKER; } else if (ak == AdviceKind.After || ak == AdviceKind.AfterReturning || ak == AdviceKind.AfterThrowing) { markerType = IAJModelMarker.AFTER_ADVICE_MARKER; } else if (ak == AdviceKind.Around) { markerType = IAJModelMarker.AROUND_ADVICE_MARKER; } else { markerType = IAJModelMarker.ADVICE_MARKER; } } } else if (name.equals(AsmRelationshipProvider.ADVISES)) { IProgramElement advice = model.getProgramElement(relationship.getSourceHandle()); AdviceKind ak; if (advice.getExtraInfo() != null) { ak = AdviceKind.stringToKind(advice.getExtraInfo().getExtraAdviceInformation()); } else { ak = null; // hmmm...sometmes ExtradviceInformtion is null. // try to get the advice kind by the name if (advice.getName().startsWith("before")) { ak = AdviceKind.Before; } else if (advice.getName().startsWith("after")) { ak = AdviceKind.After; } else if (advice.getName().startsWith("around")) { ak = AdviceKind.Around; } } if (runtimeTest) { if (ak == null) { markerType = IAJModelMarker.SOURCE_DYNAMIC_ADVICE_MARKER; } else if (ak == AdviceKind.Before) { markerType = IAJModelMarker.SOURCE_DYNAMIC_BEFORE_ADVICE_MARKER; } else if (ak == AdviceKind.After || ak == AdviceKind.AfterReturning || ak == AdviceKind.AfterThrowing) { markerType = IAJModelMarker.SOURCE_DYNAMIC_AFTER_ADVICE_MARKER; } else if (ak == AdviceKind.Around) { markerType = IAJModelMarker.SOURCE_DYNAMIC_AROUND_ADVICE_MARKER; } else { markerType = IAJModelMarker.SOURCE_DYNAMIC_ADVICE_MARKER; } } else { // no runtime test if (ak == null) { markerType = IAJModelMarker.SOURCE_ADVICE_MARKER; } else if (ak == AdviceKind.Before) { markerType = IAJModelMarker.SOURCE_BEFORE_ADVICE_MARKER; } else if (ak == AdviceKind.After || ak == AdviceKind.AfterReturning || ak == AdviceKind.AfterThrowing) { markerType = IAJModelMarker.SOURCE_AFTER_ADVICE_MARKER; } else if (ak == AdviceKind.Around) { markerType = IAJModelMarker.SOURCE_AROUND_ADVICE_MARKER; } else { markerType = IAJModelMarker.SOURCE_ADVICE_MARKER; } } } else if (name.equals(AsmRelationshipProvider.ANNOTATED_BY) || name.equals(AsmRelationshipProvider.SOFTENED_BY) || name.equals(AsmRelationshipProvider.INTER_TYPE_DECLARED_BY)) { // note that we ignore MATCHES_DECLARE because that is taken care of // by error and warning markers markerType = IAJModelMarker.ITD_MARKER; } else if (name.equals(AsmRelationshipProvider.ANNOTATES) || name.equals(AsmRelationshipProvider.INTER_TYPE_DECLARES) || name.equals(AsmRelationshipProvider.SOFTENS) || name.equals(AsmRelationshipProvider.MATCHED_BY)) { markerType = IAJModelMarker.SOURCE_ITD_MARKER; } else { markerType = null; } return markerType; } private String getMultipleMarkersLabel(int number) { return number + " " + UIMessages.AspectJMarkersAtLine; //$NON-NLS-1$ } private String getMarkerLabel(List<IRelationship> relationships) { // find first non-matches declare relationship for (IRelationship rel : relationships) { if (!rel.getName().equals(AsmRelationshipProvider.MATCHES_DECLARE)) { return getMarkerLabel(rel); } } return "<none>"; } /** * Get a label for the given relationship * * @param relationship * @return */ private String getMarkerLabel(IRelationship relationship) { IProgramElement target = model.getProgramElement((String) relationship.getTargets().get(0)); return relationship.getName() + " " //$NON-NLS-1$ + (target != null ? target.toLinkLabelString(false) : "null") + (relationship.hasRuntimeTest() ? " " + //$NON-NLS-1$ UIMessages.AspectJEditor_runtimetest : ""); //$NON-NLS-1$ } /** * check if this relationship comes from an aspect that has a custom marker * @see AJMarkersDialog */ private String getCustomMarker(IRelationship relationship) { // get the element in the aspect, it is source or target depending // on the kind of relationship List<IJavaElement> aspectEntities = new ArrayList<IJavaElement>(); if (relationship.isAffects()) { aspectEntities.add(model.programElementToJavaElement(relationship.getSourceHandle())); } else { // all targets are from the same for (String target : relationship.getTargets()) { aspectEntities.add(model.programElementToJavaElement(target)); } } for (IJavaElement elt : aspectEntities) { if (elt != null) { // will be null if the referent is not found. Should only be in error cases IType typeElement = (IType) elt.getAncestor(IJavaElement.TYPE); if (typeElement != null) { String customImage = AspectJPreferences.getSavedIcon(typeElement.getJavaProject().getProject(), AJMarkersDialog.getFullyQualifiedAspectName(typeElement)); if (customImage != null) { return customImage; } } } } return null; } /** * Two or more markers on the same line - get the most approriate marker * type to display * * @param firstMarkerType * @param secondMarkerType * @param runtimeTest * @return */ private String getCombinedMarkerType(String firstMarkerType, String secondMarkerType, boolean runtimeTest) { if (firstMarkerType.indexOf("source") != -1 && secondMarkerType.indexOf("source") != -1) { //$NON-NLS-1$ //$NON-NLS-2$ // around advice trumps before and after if (firstMarkerType.indexOf("around") != -1 || secondMarkerType.indexOf("around") != -1) { //$NON-NLS-1$ //$NON-NLS-2$ return runtimeTest ? IAJModelMarker.SOURCE_DYNAMIC_AROUND_ADVICE_MARKER : IAJModelMarker.SOURCE_AROUND_ADVICE_MARKER; } else { return runtimeTest ? IAJModelMarker.SOURCE_DYNAMIC_ADVICE_MARKER : IAJModelMarker.SOURCE_ADVICE_MARKER; } } else if (firstMarkerType.indexOf("source") != -1 || secondMarkerType.indexOf("source") != -1) { //$NON-NLS-1$ //$NON-NLS-2$ // being source and target trumps around, before, and after return runtimeTest ? IAJModelMarker.DYNAMIC_SOURCE_AND_TARGET_MARKER : IAJModelMarker.SOURCE_AND_TARGET_MARKER; } else { // around advice trumps before and after if (firstMarkerType.indexOf("around") != -1 || secondMarkerType.indexOf("around") != -1) { //$NON-NLS-1$ //$NON-NLS-2$ return runtimeTest ? IAJModelMarker.DYNAMIC_AROUND_ADVICE_MARKER : IAJModelMarker.AROUND_ADVICE_MARKER; } else { return runtimeTest ? IAJModelMarker.DYNAMIC_ADVICE_MARKER : IAJModelMarker.ADVICE_MARKER; } } } }