18da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal/* 28da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * Copyright 2010 Google Inc. 38da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * 48da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * Licensed under the Apache License, Version 2.0 (the "License"); 58da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * you may not use this file except in compliance with the License. 68da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * You may obtain a copy of the License at 78da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * 88da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * http://www.apache.org/licenses/LICENSE-2.0 98da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * 108da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * Unless required by applicable law or agreed to in writing, software 118da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * distributed under the License is distributed on an "AS IS" BASIS, 128da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * See the License for the specific language governing permissions and 148da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * limitations under the License. 158da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal */ 168da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalpackage com.google.android.testing.mocking; 178da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal 188da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport javassist.CannotCompileException; 198da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal 208da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport java.io.FileNotFoundException; 218da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport java.io.IOException; 228da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport java.io.OutputStream; 238da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport java.util.ArrayList; 248da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport java.util.HashSet; 258da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport java.util.List; 268da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport java.util.Set; 278da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal 288da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport javax.annotation.processing.AbstractProcessor; 298da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport javax.annotation.processing.RoundEnvironment; 308da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport javax.annotation.processing.SupportedAnnotationTypes; 318da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport javax.annotation.processing.SupportedOptions; 328da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport javax.annotation.processing.SupportedSourceVersion; 338da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport javax.lang.model.SourceVersion; 348da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport javax.lang.model.element.AnnotationMirror; 358da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport javax.lang.model.element.AnnotationValue; 368da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport javax.lang.model.element.Element; 378da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport javax.lang.model.element.TypeElement; 388da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport javax.tools.Diagnostic.Kind; 398da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalimport javax.tools.JavaFileObject; 408da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal 418da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal 428da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal/** 438da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * Annotation Processor to generate the mocks for Android Mock. 448da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * 458da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * This processor will automatically create mocks for all classes 468da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * specified by {@link UsesMocks} annotations. 478da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * 488da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * @author swoodward@google.com (Stephen Woodward) 498da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal */ 508da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal@SupportedAnnotationTypes("com.google.android.testing.mocking.UsesMocks") 518da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal@SupportedSourceVersion(SourceVersion.RELEASE_5) 528da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal@SupportedOptions({ 538da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal UsesMocksProcessor.REGENERATE_FRAMEWORK_MOCKS, 548da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal UsesMocksProcessor.LOGFILE, 558da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal UsesMocksProcessor.BIN_DIR 568da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal}) 578da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigalpublic class UsesMocksProcessor extends AbstractProcessor { 588da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal public static final String LOGFILE = "logfile"; 598da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal public static final String REGENERATE_FRAMEWORK_MOCKS = "RegenerateFrameworkMocks"; 608da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal public static final String BIN_DIR = "bin_dir"; 618da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal private AndroidMockGenerator mockGenerator = new AndroidMockGenerator(); 628da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal private AndroidFrameworkMockGenerator frameworkMockGenerator = 638da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal new AndroidFrameworkMockGenerator(); 648da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal ProcessorLogger logger; 658da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal 668da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal /** 678da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * Main entry point of the processor. This is called by the Annotation framework. 688da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * {@link javax.annotation.processing.AbstractProcessor} for more details. 698da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal */ 708da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal @Override 718da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment) { 728da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal try { 738da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal prepareLogger(); 748da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal List<Class<?>> classesToMock = getClassesToMock(environment); 758da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal Set<GeneratedClassFile> mockedClassesSet = getMocksFor(classesToMock); 768da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal writeMocks(mockedClassesSet); 778da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } catch (Exception e) { 788da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.printMessage(Kind.ERROR, e); 798da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } finally { 808da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.close(); 818da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 828da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal return false; 838da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 848da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal 858da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal /** 868da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * Returns a Set of GeneratedClassFile objects which represent all of the classes to be mocked. 878da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * 888da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * @param classesToMock the list of classes which need to be mocked. 898da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * @return a set of mock support classes to support the mocking of all the classes specified in 908da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * {@literal classesToMock}. 918da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal */ 928da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal private Set<GeneratedClassFile> getMocksFor(List<Class<?>> classesToMock) throws IOException, 938da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal CannotCompileException { 948da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.printMessage(Kind.NOTE, "Found " + classesToMock.size() + " classes to mock"); 958da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal boolean regenerateFrameworkMocks = processingEnv.getOptions().get( 968da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal REGENERATE_FRAMEWORK_MOCKS) != null; 978da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal if (regenerateFrameworkMocks) { 988da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.printMessage(Kind.NOTE, "Regenerating Framework Mocks on Request"); 998da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1008da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal Set<GeneratedClassFile> mockedClassesSet = 1018da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal getClassMocks(classesToMock, regenerateFrameworkMocks); 1028da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.printMessage(Kind.NOTE, "Found " + mockedClassesSet.size() 1038da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal + " mocked classes to save"); 1048da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal return mockedClassesSet; 1058da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1068da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal 1078da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal /** 1088da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * @param environment the environment for this round of processing as provided to the main 1098da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * {@link #process(Set, RoundEnvironment)} method. 1108da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * @return a List of Class objects for the classes that need to be mocked. 1118da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal */ 1128da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal private List<Class<?>> getClassesToMock(RoundEnvironment environment) { 1138da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.printMessage(Kind.NOTE, "Start Processing Annotations"); 1148da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal List<Class<?>> classesToMock = new ArrayList<Class<?>>(); 1158da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal classesToMock.addAll( 1168da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal findClassesToMock(environment.getElementsAnnotatedWith(UsesMocks.class))); 1178da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal return classesToMock; 1188da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1198da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal 1208da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal private void prepareLogger() { 1218da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal if (logger == null) { 1228da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger = new ProcessorLogger(processingEnv.getOptions().get(LOGFILE), processingEnv); 1238da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1248da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1258da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal 1268da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal /** 1278da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * Finds all of the classes that should be mocked, based on {@link UsesMocks} annotations 1288da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * in the various source files being compiled. 1298da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * 1308da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * @param annotatedElements a Set of all elements holding {@link UsesMocks} annotations. 1318da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * @return all of the classes that should be mocked. 1328da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal */ 1338da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal List<Class<?>> findClassesToMock(Set<? extends Element> annotatedElements) { 1348da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.printMessage(Kind.NOTE, "Processing " + annotatedElements); 1358da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal List<Class<?>> classList = new ArrayList<Class<?>>(); 1368da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal for (Element annotation : annotatedElements) { 1378da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal List<? extends AnnotationMirror> mirrors = annotation.getAnnotationMirrors(); 1388da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal for (AnnotationMirror mirror : mirrors) { 1398da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal if (mirror.getAnnotationType().toString().equals(UsesMocks.class.getName())) { 1408da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal for (AnnotationValue annotationValue : mirror.getElementValues().values()) { 1418da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal for (Object classFileName : (Iterable<?>) annotationValue.getValue()) { 1428da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal String className = classFileName.toString(); 1438da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal if (className.endsWith(".class")) { 1448da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal className = className.substring(0, className.length() - 6); 1458da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1468da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.printMessage(Kind.NOTE, "Adding Class to Mocking List: " + className); 1478da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal try { 1488da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal classList.add(Class.forName(className, false, getClass().getClassLoader())); 1498da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } catch (ClassNotFoundException e) { 1508da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.reportClasspathError(className, e); 1518da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1528da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1538da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1548da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1558da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1568da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1578da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal return classList; 1588da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1598da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal 1608da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal /** 1618da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * Gets a set of GeneratedClassFiles to represent all of the support classes required to 1628da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * mock the List of classes provided in {@code classesToMock}. 1638da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * @param classesToMock the list of classes to be mocked. 1648da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * @param regenerateFrameworkMocks if true, then mocks for the framework classes will be created 1658da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * instead of pulled from the existing set of framework support classes. 1668da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * @return a Set of {@link GeneratedClassFile} for all of the mocked classes. 1678da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal */ 1688da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal Set<GeneratedClassFile> getClassMocks(List<Class<?>> classesToMock, 1698da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal boolean regenerateFrameworkMocks) throws IOException, CannotCompileException { 1708da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal Set<GeneratedClassFile> mockedClassesSet = new HashSet<GeneratedClassFile>(); 1718da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal for (Class<?> clazz : classesToMock) { 1728da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal try { 1738da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.printMessage(Kind.NOTE, "Mocking " + clazz); 1748da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal if (!AndroidMock.isAndroidClass(clazz) || regenerateFrameworkMocks) { 1758da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal mockedClassesSet.addAll(getAndroidMockGenerator().createMocksForClass(clazz)); 1768da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } else { 1778da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal mockedClassesSet.addAll(getAndroidFrameworkMockGenerator().getMocksForClass(clazz)); 1788da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1798da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } catch (ClassNotFoundException e) { 1808da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.reportClasspathError(clazz.getName(), e); 1818da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } catch (NoClassDefFoundError e) { 1828da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.reportClasspathError(clazz.getName(), e); 1838da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1848da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1858da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal return mockedClassesSet; 1868da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1878da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal 1888da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal private AndroidFrameworkMockGenerator getAndroidFrameworkMockGenerator() { 1898da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal return frameworkMockGenerator; 1908da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 1918da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal 1928da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal /** 1938da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * Writes the provided mocks from {@code mockedClassesSet} to the bin folder alongside the 1948da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * .class files being generated by the javac call which invoked this annotation processor. 1958da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * In Eclipse, additional information is needed as the Eclipse annotation processor framework 1968da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * is missing key functionality required by this method. Instead the classes are saved using 1978da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * a FileOutputStream and the -Abin_dir processor option must be set. 1988da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * @param mockedClassesSet the set of mocks to be saved. 1998da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal */ 2008da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal void writeMocks(Set<GeneratedClassFile> mockedClassesSet) { 2018da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal for (GeneratedClassFile clazz : mockedClassesSet) { 2028da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal OutputStream classFileStream; 2038da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal try { 2048da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.printMessage(Kind.NOTE, "Saving " + clazz.getClassName()); 2058da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal JavaFileObject classFile = processingEnv.getFiler().createClassFile(clazz.getClassName()); 2068da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal classFileStream = classFile.openOutputStream(); 2078da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal classFileStream.write(clazz.getContents()); 2088da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal classFileStream.close(); 2098da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } catch (IOException e) { 2108da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.printMessage(Kind.ERROR, "Internal Error saving mock: " + clazz.getClassName()); 2118da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.printMessage(Kind.ERROR, e); 2128da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } catch (UnsupportedOperationException e) { 2138da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal // Eclipse annotation processing doesn't support class creation. 2148da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.printMessage(Kind.NOTE, "Saving via Eclipse " + clazz.getClassName()); 2158da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal saveMocksEclipse(clazz, processingEnv.getOptions().get(BIN_DIR).toString().trim()); 2168da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 2178da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 2188da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.printMessage(Kind.NOTE, "Finished Processing Mocks"); 2198da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 2208da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal 2218da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal /** 2228da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * Workaround to save the mocks for Eclipse's annotation processing framework which doesn't 2238da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * support the JavaFileObject object. 2248da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * @param clazz the class to save. 2258da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal * @param outputFolderName the output folder where the class will be saved. 2268da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal */ 2278da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal private void saveMocksEclipse(GeneratedClassFile clazz, String outputFolderName) { 2288da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal try { 2298da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal FileUtils.saveClassToFolder(clazz, outputFolderName); 2308da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } catch (FileNotFoundException e) { 2318da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.printMessage(Kind.ERROR, e); 2328da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } catch (IOException e) { 2338da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal logger.printMessage(Kind.ERROR, e); 2348da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 2358da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 2368da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal 2378da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal private AndroidMockGenerator getAndroidMockGenerator() { 2388da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal return mockGenerator; 2398da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal } 2408da3e6ec64b991f5aa1e6561941d130683eba753Luis Sigal} 241