1 /* *******************************************************************
2 * Copyright (c) 2002 IBM and other contributors
4 * This program and the accompanying materials are made available
5 * under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Palo Alto Research Center, Incorporated (PARC)
12 * ******************************************************************/
14 package org.aspectj.ajdt.internal.core.builder;
17 import java.io.IOException;
18 import java.util.Collections;
19 import java.util.HashMap;
20 import java.util.HashSet;
24 import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation;
25 import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileReader;
26 import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFormatException;
27 import org.aspectj.org.eclipse.jdt.internal.compiler.env.IBinaryType;
28 import org.aspectj.org.eclipse.jdt.internal.compiler.env.IModule;
29 import org.aspectj.org.eclipse.jdt.internal.compiler.env.IModuleAwareNameEnvironment;
30 import org.aspectj.org.eclipse.jdt.internal.compiler.env.NameEnvironmentAnswer;
31 import org.aspectj.util.FileUtil;
33 public class StatefulNameEnvironment implements IModuleAwareNameEnvironment {
34 private Map<String,File> classesFromName;
35 private Map<String,NameEnvironmentAnswer> inflatedClassFilesCache;
36 private Set<String> packageNames;
37 private AjState state;
38 private IModuleAwareNameEnvironment baseEnvironment;
40 public StatefulNameEnvironment(IModuleAwareNameEnvironment baseEnvironment, Map<String,File> classesFromName, AjState state) {
41 this.classesFromName = classesFromName;
42 this.inflatedClassFilesCache = new HashMap<String,NameEnvironmentAnswer>();
43 this.baseEnvironment = baseEnvironment;
45 packageNames = new HashSet<String>();
46 for (String className: classesFromName.keySet()) {
47 addAllPackageNames(className);
51 private void addAllPackageNames(String className) {
52 int dot = className.indexOf('.');
54 packageNames.add(className.substring(0, dot));
55 dot = className.indexOf('.', dot + 1);
59 private NameEnvironmentAnswer findType(String name) {
60 // pr133532 - ask the state for the type first
61 IBinaryType seenOnPreviousBuild = state.checkPreviousBuild(name);
62 if (seenOnPreviousBuild != null) {
63 return new NameEnvironmentAnswer(seenOnPreviousBuild, null);
65 if (this.inflatedClassFilesCache.containsKey(name)) {
66 return (NameEnvironmentAnswer) this.inflatedClassFilesCache.get(name);
68 File fileOnDisk = (File) classesFromName.get(name);
69 // System.err.println("find: " + name + " found: " + cf);
70 if (fileOnDisk == null) {
74 // System.out.println("from cache: " + name);
75 byte[] bytes = FileUtil.readAsByteArray(fileOnDisk);
76 NameEnvironmentAnswer ret = new NameEnvironmentAnswer(new ClassFileReader(bytes, fileOnDisk.getAbsolutePath()
77 .toCharArray()), null /* no access restriction */);
78 this.inflatedClassFilesCache.put(name, ret);
80 } catch (ClassFormatException e) {
81 return null; // !!! seems to match FileSystem behavior
82 } catch (IOException ex) {
83 return null; // see above...
89 public void cleanup() {
90 baseEnvironment.cleanup();
91 this.classesFromName = Collections.emptyMap();
92 this.packageNames.clear();
96 public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName) {
97 NameEnvironmentAnswer ret = findType(new String(CharOperation.concatWith(packageName, typeName, '.')));
101 return baseEnvironment.findType(typeName, packageName);
105 public NameEnvironmentAnswer findType(char[][] compoundName) {
106 NameEnvironmentAnswer ret = findType(new String(CharOperation.concatWith(compoundName, '.')));
110 return baseEnvironment.findType(compoundName);
114 public boolean isPackage(char[][] parentPackageName, char[] packageName) {
115 if (baseEnvironment.isPackage(parentPackageName, packageName)) {
118 String fullPackageName = new String(CharOperation.concatWith(parentPackageName, packageName, '.'));
119 return packageNames.contains(fullPackageName);
123 * Needs to be told about changes. The 'added' set is a subset of classNameToFileMap consisting of just those names added during
124 * this build - to reduce any impact on incremental compilation times.
126 public void update(Map<String,File> classNameToFileMap, Set<String> added) {
127 for (String className: added) {
128 addAllPackageNames(className);
130 this.classesFromName = classNameToFileMap;
134 public NameEnvironmentAnswer findType(char[][] compoundName, char[] moduleName) {
135 return baseEnvironment.findType(compoundName, moduleName);
139 public NameEnvironmentAnswer findType(char[] typeName, char[][] packageName, char[] moduleName) {
140 return baseEnvironment.findType(typeName, packageName, moduleName);
144 public char[][] getModulesDeclaringPackage(char[][] parentPackageName, char[] name, char[] moduleName) {
145 return baseEnvironment.getModulesDeclaringPackage(parentPackageName, name, moduleName);
149 public boolean hasCompilationUnit(char[][] qualifiedPackageName, char[] moduleName, boolean checkCUs) {
150 return baseEnvironment.hasCompilationUnit(qualifiedPackageName, moduleName, checkCUs);
154 public IModule getModule(char[] moduleName) {
155 return baseEnvironment.getModule(moduleName);
159 public char[][] getAllAutomaticModules() {
160 return baseEnvironment.getAllAutomaticModules();