Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/* *******************************************************************
* Copyright (c) 2003 Contributors.
* 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:
* Mik Kersten initial implementation
* Andy Clement incremental support and switch on/off state
* ******************************************************************/
package org.aspectj.asm;
import java.io.BufferedWriter;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.aspectj.asm.internal.AspectJElementHierarchy;
import org.aspectj.asm.internal.HandleProviderDelimiter;
import org.aspectj.asm.internal.JDTLikeHandleProvider;
import org.aspectj.asm.internal.RelationshipMap;
import org.aspectj.bridge.ISourceLocation;
import org.aspectj.util.IStructureModel;
/**
* The Abstract Structure Model (ASM) represents the containment hierarchy and crosscutting structure map for AspectJ programs. It
* is used by IDE views such as the document outline, and by other tools such as ajdoc to show both AspectJ declarations and
* crosscutting links, such as which advice affects which join point shadows.
*
* @author Mik Kersten
* @author Andy Clement
*/
public class AsmManager implements IStructureModel {
// For testing ONLY
public static boolean recordingLastActiveStructureModel = true;
public static AsmManager lastActiveStructureModel;
public static boolean forceSingletonBehaviour = false;
// SECRETAPI asc pull the secret options together into a system API you lazy fool
public static boolean attemptIncrementalModelRepairs = false;
// Dumping the model is expensive
public static boolean dumpModelPostBuild = false;
// For offline debugging, you can now ask for the AsmManager to
// dump the model - see the method setReporting()
private static boolean dumpModel = false;
private static boolean dumpRelationships = false;
private static boolean dumpDeltaProcessing = false;
private static IModelFilter modelFilter = null;
private static String dumpFilename = "";
private static boolean reporting = false;
private static boolean completingTypeBindings = false;
private final List structureListeners = new ArrayList();
// The model is 'manipulated' by the AjBuildManager.setupModel() code which
// trashes all the
// fields when setting up a new model for a batch build.
// Due to the requirements of incremental compilation we need to tie some of
// the info
// below to the AjState for a compilation and recover it if switching
// between projects.
protected IHierarchy hierarchy;
/*
* Map from String > String - it maps absolute paths for inpath dirs/jars to workspace relative paths suitable for handle
* inclusion
*/
protected Map inpathMap;
private IRelationshipMap mapper;
private IElementHandleProvider handleProvider;
private final CanonicalFilePathMap canonicalFilePathMap = new CanonicalFilePathMap();
// Record the Set for which the model has been modified during the
// last incremental build
private final Set lastBuildChanges = new HashSet();
// Record the Set of aspects that wove the files listed in lastBuildChanges
final Set aspectsWeavingInLastBuild = new HashSet();
// static {
// setReporting("c:/model.nfo",true,true,true,true);
// }
private AsmManager() {
}
public static AsmManager createNewStructureModel(Map inpathMap) {
if (forceSingletonBehaviour && lastActiveStructureModel != null) {
return lastActiveStructureModel;
}
AsmManager asm = new AsmManager();
asm.inpathMap = inpathMap;
asm.hierarchy = new AspectJElementHierarchy(asm);
asm.mapper = new RelationshipMap();
asm.handleProvider = new JDTLikeHandleProvider(asm);
// call initialize on the handleProvider when we create a new ASM
// to give handleProviders the chance to reset any state
asm.handleProvider.initialize();
asm.resetDeltaProcessing();
setLastActiveStructureModel(asm);
return asm;
}
public IHierarchy getHierarchy() {
return hierarchy;
}
public IRelationshipMap getRelationshipMap() {
return mapper;
}
public void fireModelUpdated() {
notifyListeners();
if (dumpModelPostBuild && hierarchy.getConfigFile() != null) {
writeStructureModel(hierarchy.getConfigFile());
}
}
/**
* Constructs map each time it's called.
*/
public HashMap> getInlineAnnotations(String sourceFile, boolean showSubMember,
boolean showMemberAndType) {
if (!hierarchy.isValid()) {
return null;
}
HashMap> annotations = new HashMap>();
IProgramElement node = hierarchy.findElementForSourceFile(sourceFile);
if (node == IHierarchy.NO_STRUCTURE) {
return null;
} else {
IProgramElement fileNode = node;
ArrayList peNodes = new ArrayList();
getAllStructureChildren(fileNode, peNodes, showSubMember, showMemberAndType);
for (Iterator it = peNodes.iterator(); it.hasNext();) {
IProgramElement peNode = it.next();
List entries = new ArrayList();
entries.add(peNode);
ISourceLocation sourceLoc = peNode.getSourceLocation();
if (null != sourceLoc) {
Integer hash = new Integer(sourceLoc.getLine());
List existingEntry = annotations.get(hash);
if (existingEntry != null) {
entries.addAll(existingEntry);
}
annotations.put(hash, entries);
}
}
return annotations;
}
}
private void getAllStructureChildren(IProgramElement node, List result, boolean showSubMember,
boolean showMemberAndType) {
List children = node.getChildren();
if (node.getChildren() == null) {
return;
}
for (IProgramElement next : children) {
List rels = mapper.get(next);
if (next != null
&& ((next.getKind() == IProgramElement.Kind.CODE && showSubMember) || (next.getKind() != IProgramElement.Kind.CODE && showMemberAndType))
&& rels != null && rels.size() > 0) {
result.add(next);
}
getAllStructureChildren(next, result, showSubMember, showMemberAndType);
}
}
public void addListener(IHierarchyListener listener) {
structureListeners.add(listener);
}
public void removeStructureListener(IHierarchyListener listener) {
structureListeners.remove(listener);
}
// this shouldn't be needed - but none of the people that add listeners
// in the test suite ever remove them. AMC added this to be called in
// setup() so that the test cases would cease leaking listeners and go
// back to executing at a reasonable speed.
public void removeAllListeners() {
structureListeners.clear();
}
private void notifyListeners() {
for (IHierarchyListener listener : structureListeners) {
listener.elementsUpdated(hierarchy);
}
}
public IElementHandleProvider getHandleProvider() {
return handleProvider;
}
public void setHandleProvider(IElementHandleProvider handleProvider) {
this.handleProvider = handleProvider;
}
public void writeStructureModel(String configFilePath) {
try {
String filePath = genExternFilePath(configFilePath);
FileOutputStream fos = new FileOutputStream(filePath);
ObjectOutputStream s = new ObjectOutputStream(fos);
s.writeObject(hierarchy); // Store the program element tree
s.writeObject(mapper); // Store the relationships
s.flush();
fos.flush();
fos.close();
s.close();
} catch (IOException e) {
// System.err.println("AsmManager: Unable to write structure model: "
// +configFilePath+" because of:");
// e.printStackTrace();
}
}
/**
* @param configFilePath path to an ".lst" file
*/
public void readStructureModel(String configFilePath) {
boolean hierarchyReadOK = false;
try {
if (configFilePath == null) {
hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
} else {
String filePath = genExternFilePath(configFilePath);
FileInputStream in = new FileInputStream(filePath);
ObjectInputStream s = new ObjectInputStream(in);
hierarchy = (AspectJElementHierarchy) s.readObject();
((AspectJElementHierarchy) hierarchy).setAsmManager(this);
hierarchyReadOK = true;
mapper = (RelationshipMap) s.readObject();
s.close();
}
} catch (FileNotFoundException fnfe) {
// That is OK
hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
} catch (EOFException eofe) {
// Might be an old format sym file that is missing its relationships
if (!hierarchyReadOK) {
System.err.println("AsmManager: Unable to read structure model: " + configFilePath + " because of:");
eofe.printStackTrace();
hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
}
} catch (Exception e) {
// System.err.println("AsmManager: Unable to read structure model: "+
// configFilePath+" because of:");
// e.printStackTrace();
hierarchy.setRoot(IHierarchy.NO_STRUCTURE);
} finally {
notifyListeners();
}
}
private String genExternFilePath(String configFilePath) {
// sometimes don't have ".lst"
if (configFilePath.lastIndexOf(".lst") != -1) {
configFilePath = configFilePath.substring(0, configFilePath.lastIndexOf(".lst"));
}
return configFilePath + ".ajsym";
}
public String getCanonicalFilePath(File f) {
return canonicalFilePathMap.get(f);
}
public CanonicalFilePathMap getCanonicalFilePathMap() {
return canonicalFilePathMap;
}
private static class CanonicalFilePathMap {
private static final int MAX_SIZE = 4000;
private final Map pathMap = new HashMap(20);
// // guards to ensure correctness and liveness
// private boolean cacheInUse = false;
// private boolean stopRequested = false;
//
// private synchronized boolean isCacheInUse() {
// return cacheInUse;
// }
//
// private synchronized void setCacheInUse(boolean val) {
// cacheInUse = val;
// if (val) {
// notifyAll();
// }
// }
//
// private synchronized boolean isStopRequested() {
// return stopRequested;
// }
//
// private synchronized void requestStop() {
// stopRequested = true;
// }
//
// /**
// * Begin prepopulating the map by adding an entry from
// * file.getPath -> file.getCanonicalPath for each file in
// * the list. Do this on a background thread.
// * @param files
// */
// public void prepopulate(final List files) {
// stopRequested = false;
// setCacheInUse(false);
// if (pathMap.size() > MAX_SIZE) {
// pathMap.clear();
// }
// new Thread() {
// public void run() {
// System.out.println("Starting cache population: " +
// System.currentTimeMillis());
// Iterator it = files.iterator();
// while (!isStopRequested() && it.hasNext()) {
// File f = (File)it.next();
// if (pathMap.get(f.getPath()) == null) {
// // may reuse cache across compiles from ides...
// try {
// pathMap.put(f.getPath(),f.getCanonicalPath());
// } catch (IOException ex) {
// pathMap.put(f.getPath(),f.getPath());
// }
// }
// }
// System.out.println("Cached " + files.size());
// setCacheInUse(true);
// System.out.println("Cache populated: " + System.currentTimeMillis());
// }
// }.start();
// }
//
// /**
// * Stop pre-populating the cache - our customers are ready to use it.
// * If there are any cache misses from this point on, we'll populate
// the
// * cache as we go.
// * The handover is done this way to ensure that only one thread is
// ever
// * accessing the cache, and that we minimize synchronization.
// */
// public synchronized void handover() {
// if (!isCacheInUse()) {
// requestStop();
// try {
// while (!isCacheInUse()) wait();
// } catch (InterruptedException intEx) { } // just continue
// }
// }
public String get(File f) {
// if (!cacheInUse) { // unsynchronized test - should never be
// parallel
// // threads at this point
// throw new IllegalStateException(
// "Must take ownership of cache before using by calling " +
// "handover()");
// }
String ret = pathMap.get(f.getPath());
if (ret == null) {
try {
ret = f.getCanonicalPath();
} catch (IOException ioEx) {
ret = f.getPath();
}
pathMap.put(f.getPath(), ret);
if (pathMap.size() > MAX_SIZE) {
pathMap.clear();
}
}
return ret;
}
}
// SECRETAPI
public static void setReporting(String filename, boolean dModel, boolean dRels, boolean dDeltaProcessing, boolean deletefile) {
reporting = true;
dumpModel = dModel;
dumpRelationships = dRels;
dumpDeltaProcessing = dDeltaProcessing;
if (deletefile) {
new File(filename).delete();
}
dumpFilename = filename;
}
public static void setReporting(String filename, boolean dModel, boolean dRels, boolean dDeltaProcessing, boolean deletefile,
IModelFilter aFilter) {
setReporting(filename, dModel, dRels, dDeltaProcessing, deletefile);
modelFilter = aFilter;
}
public static boolean isReporting() {
return reporting;
}
public static void setDontReport() {
reporting = false;
dumpDeltaProcessing = false;
dumpModel = false;
dumpRelationships = false;
}
// NB. If the format of this report changes then the model tests
// (@see org.aspectj.systemtest.model.ModelTestCase) will fail in
// their comparison. The tests are assuming that both the model
// and relationship map are reported and as a consequence single
// testcases test that both the model and relationship map are correct.
public void reportModelInfo(String reasonForReport) {
if (!dumpModel && !dumpRelationships) {
return;
}
try {
FileWriter fw = new FileWriter(dumpFilename, true);
BufferedWriter bw = new BufferedWriter(fw);
if (dumpModel) {
bw.write("=== MODEL STATUS REPORT ========= " + reasonForReport + "\n");
dumptree(bw, hierarchy.getRoot(), 0);
bw.write("=== END OF MODEL REPORT =========\n");
}
if (dumpRelationships) {
bw.write("=== RELATIONSHIPS REPORT ========= " + reasonForReport + "\n");
dumprels(bw);
bw.write("=== END OF RELATIONSHIPS REPORT ==\n");
}
Properties p = summarizeModel().getProperties();
Enumeration