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

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