You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

WeaverAdapter.java 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /*******************************************************************************
  2. * Copyright (c) 2004 IBM Corporation and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v 2.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
  7. *
  8. * Contributors:
  9. * IBM Corporation - initial API and implementation
  10. *******************************************************************************/
  11. package org.aspectj.ajdt.internal.compiler;
  12. import java.util.Iterator;
  13. import java.util.Map;
  14. import org.aspectj.asm.internal.CharOperation;
  15. import org.aspectj.bridge.IMessage;
  16. import org.aspectj.bridge.IProgressListener;
  17. import org.aspectj.bridge.MessageUtil;
  18. import org.aspectj.org.eclipse.jdt.internal.compiler.ClassFile;
  19. import org.aspectj.org.eclipse.jdt.internal.compiler.problem.AbortCompilation;
  20. import org.aspectj.weaver.IClassFileProvider;
  21. import org.aspectj.weaver.IUnwovenClassFile;
  22. import org.aspectj.weaver.IWeaveRequestor;
  23. import org.eclipse.core.runtime.OperationCanceledException;
  24. /**
  25. * @author colyer This class provides the weaver with a source of class files to weave (via the iterator and IClassFileProvider
  26. * interfaces). It receives results back from the weaver via the IWeaveRequestor interface.
  27. */
  28. public class WeaverAdapter implements IClassFileProvider, IWeaveRequestor, Iterator {
  29. private final AbstractCompilerAdapter compilerAdapter;
  30. private Iterator<InterimCompilationResult> resultIterator;
  31. private int classFileIndex = 0;
  32. private InterimCompilationResult nowProcessing;
  33. private InterimCompilationResult lastReturnedResult;
  34. private final WeaverMessageHandler weaverMessageHandler;
  35. private final IProgressListener progressListener;
  36. private boolean finalPhase = false;
  37. private int localIteratorCounter;
  38. // Fields related to progress monitoring
  39. private int progressMaxTypes;
  40. private String progressPhasePrefix;
  41. private double fromPercent;
  42. private final double toPercent = 100.0;
  43. private int progressCompletionCount;
  44. public WeaverAdapter(AbstractCompilerAdapter forCompiler, WeaverMessageHandler weaverMessageHandler,
  45. IProgressListener progressListener) {
  46. this.compilerAdapter = forCompiler;
  47. this.weaverMessageHandler = weaverMessageHandler;
  48. this.progressListener = progressListener;
  49. }
  50. /*
  51. * (non-Javadoc)
  52. *
  53. * @see org.aspectj.weaver.IClassFileProvider#getClassFileIterator()
  54. */
  55. public Iterator getClassFileIterator() {
  56. classFileIndex = 0;
  57. localIteratorCounter = 0;
  58. nowProcessing = null;
  59. lastReturnedResult = null;
  60. resultIterator = compilerAdapter.getResultsPendingWeave().iterator();
  61. return this;
  62. }
  63. /*
  64. * (non-Javadoc)
  65. *
  66. * @see org.aspectj.weaver.IClassFileProvider#getRequestor()
  67. */
  68. public IWeaveRequestor getRequestor() {
  69. return this;
  70. }
  71. public boolean isApplyAtAspectJMungersOnly() {
  72. return false;
  73. }
  74. // Iteration
  75. // ================================================================
  76. /*
  77. * (non-Javadoc)
  78. *
  79. * @see java.util.Iterator#hasNext()
  80. */
  81. public boolean hasNext() {
  82. if (nowProcessing == null) {
  83. if (!resultIterator.hasNext())
  84. return false;
  85. nowProcessing = resultIterator.next();
  86. classFileIndex = 0;
  87. }
  88. while (nowProcessing.unwovenClassFiles().length == 0) {
  89. if (!resultIterator.hasNext())
  90. return false;
  91. nowProcessing = resultIterator.next();
  92. }
  93. if (classFileIndex < nowProcessing.unwovenClassFiles().length) {
  94. return true;
  95. } else {
  96. classFileIndex = 0;
  97. if (!resultIterator.hasNext())
  98. return false;
  99. nowProcessing = resultIterator.next();
  100. while (nowProcessing.unwovenClassFiles().length == 0) {
  101. if (!resultIterator.hasNext())
  102. return false;
  103. nowProcessing = resultIterator.next();
  104. }
  105. }
  106. return true;
  107. }
  108. /*
  109. * (non-Javadoc)
  110. *
  111. * @see java.util.Iterator#next()
  112. */
  113. public Object next() {
  114. if (!hasNext())
  115. return null; // sets up indices correctly
  116. if (finalPhase) {
  117. if ((lastReturnedResult != null) && (lastReturnedResult != nowProcessing)) {
  118. // we're done with the lastReturnedResult
  119. finishedWith(lastReturnedResult);
  120. }
  121. }
  122. localIteratorCounter++;
  123. lastReturnedResult = nowProcessing;
  124. weaverMessageHandler.setCurrentResult(nowProcessing.result());
  125. // weaverMessageHandler.handleMessage(new Message("weaving " + nowProcessing.fileName(),IMessage.INFO, null, null));
  126. return nowProcessing.unwovenClassFiles()[classFileIndex++];
  127. }
  128. /*
  129. * (non-Javadoc)
  130. *
  131. * @see java.util.Iterator#remove()
  132. */
  133. public void remove() {
  134. throw new UnsupportedOperationException();
  135. }
  136. // IWeaveRequestor
  137. // =====================================================================================
  138. // weave phases as indicated by bcelWeaver...
  139. public void processingReweavableState() {
  140. // progress reporting logic
  141. fromPercent = 50.0; // Assume weaving takes 50% of the progress bar...
  142. // recordProgress("processing reweavable state");
  143. }
  144. public void addingTypeMungers() {
  145. // progress reporting logic
  146. // At this point we have completed one iteration through all the classes/aspects
  147. // we'll be dealing with, so let us remember this max value for localIteratorCounter
  148. // (for accurate progress reporting)
  149. // recordProgress("adding type mungers");
  150. progressMaxTypes = localIteratorCounter;
  151. }
  152. public void weavingAspects() {
  153. // progress reporting logic
  154. progressPhasePrefix = "woven aspect ";
  155. progressCompletionCount = 0; // Start counting from *now*
  156. }
  157. public void weavingClasses() {
  158. finalPhase = true;
  159. // progress reporting logic
  160. progressPhasePrefix = "woven class ";
  161. }
  162. public void weaveCompleted() {
  163. if ((lastReturnedResult != null) && (!lastReturnedResult.result().hasBeenAccepted)) {
  164. finishedWith(lastReturnedResult);
  165. }
  166. lastReturnedResult = null;
  167. }
  168. /*
  169. * (non-Javadoc)
  170. *
  171. * @see org.aspectj.weaver.IWeaveRequestor#acceptResult(org.aspectj.weaver.bcel.UnwovenClassFile)
  172. */
  173. public void acceptResult(IUnwovenClassFile result) {
  174. char[] key = result.getClassNameAsChars();
  175. removeFromMap(lastReturnedResult.result().compiledTypes, key);
  176. AjClassFile ajcf = new AjClassFile(key, result.getBytes());
  177. lastReturnedResult.result().record(ajcf.fileName(), ajcf);
  178. if (!weaverMessageHandler.isIgnoring(IMessage.INFO) || progressListener != null) {
  179. StringBuilder msg = new StringBuilder();
  180. msg.append(progressPhasePrefix).append(result.getClassName()).append(" (from ").append(nowProcessing.fileName())
  181. .append(")");
  182. weaverMessageHandler.handleMessage(MessageUtil.info(msg.toString()));
  183. if (progressListener != null) {
  184. progressCompletionCount++;
  185. // Smoothly take progress from 'fromPercent' to 'toPercent'
  186. recordProgress(fromPercent + ((progressCompletionCount / (double) progressMaxTypes) * (toPercent - fromPercent)),
  187. msg.toString());
  188. // progressPhasePrefix+result.getClassName()+" (from "+nowProcessing.fileName()+")");
  189. if (progressListener.isCancelledRequested()) {
  190. throw new AbortCompilation(true, new OperationCanceledException("Weaving cancelled as requested"));
  191. }
  192. }
  193. }
  194. }
  195. // helpers...
  196. // =================================================================
  197. private void finishedWith(InterimCompilationResult result) {
  198. compilerAdapter.acceptResult(result.result());
  199. }
  200. private boolean removeFromMap(Map<char[], ClassFile> aMap, char[] key) {
  201. // jdt uses char[] as a key in the hashtable, which is not very useful as equality is based on being
  202. // the same array, not having the same content.
  203. // String skey = new String(key);
  204. // OPTIMIZE what is this code for?
  205. if (aMap.remove(key) != null) {
  206. return true;
  207. }
  208. char[] victim = null;
  209. for (Object o : aMap.keySet()) {
  210. char[] thisKey = (char[]) o;
  211. if (CharOperation.equals(thisKey, key)) {
  212. // if (skey.equals(new String(thisKey))) {
  213. victim = thisKey;
  214. break;
  215. }
  216. }
  217. if (victim != null) {
  218. aMap.remove(victim);
  219. return true;
  220. }
  221. return false;
  222. }
  223. private void recordProgress(double percentage, String message) {
  224. if (progressListener != null) {
  225. progressListener.setProgress(percentage / 100);
  226. progressListener.setText(message);
  227. }
  228. }
  229. }